]> git.sur5r.net Git - openldap/commitdiff
Sync with HEAD
authorKurt Zeilenga <kurt@openldap.org>
Mon, 11 Jul 2005 07:55:29 +0000 (07:55 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Mon, 11 Jul 2005 07:55:29 +0000 (07:55 +0000)
71 files changed:
servers/slapd/acl.c
servers/slapd/aclparse.c
servers/slapd/back-bdb/attr.c
servers/slapd/back-bdb/config.c
servers/slapd/back-bdb/dn2id.c
servers/slapd/back-bdb/id2entry.c
servers/slapd/back-bdb/init.c
servers/slapd/back-bdb/search.c
servers/slapd/back-bdb/tools.c
servers/slapd/back-ldap/add.c
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/compare.c
servers/slapd/back-ldap/config.c
servers/slapd/back-ldap/delete.c
servers/slapd/back-ldap/extended.c
servers/slapd/back-ldap/init.c
servers/slapd/back-ldap/modify.c
servers/slapd/back-ldap/modrdn.c
servers/slapd/back-ldap/proto-ldap.h
servers/slapd/back-ldap/search.c
servers/slapd/back-ldap/unbind.c
servers/slapd/back-ldbm/entry.c
servers/slapd/back-ldif/ldif.c
servers/slapd/back-meta/add.c
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/candidates.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/init.c
servers/slapd/back-meta/map.c
servers/slapd/back-meta/modify.c
servers/slapd/back-meta/modrdn.c
servers/slapd/back-meta/search.c
servers/slapd/back-meta/unbind.c
servers/slapd/back-sql/init.c
servers/slapd/backend.c
servers/slapd/backover.c
servers/slapd/bconfig.c
servers/slapd/bind.c
servers/slapd/component.c
servers/slapd/config.c
servers/slapd/config.h
servers/slapd/connection.c
servers/slapd/controls.c
servers/slapd/daemon.c
servers/slapd/filter.c
servers/slapd/frontend.c
servers/slapd/init.c
servers/slapd/operational.c
servers/slapd/overlays/Makefile.in
servers/slapd/overlays/accesslog.c
servers/slapd/overlays/glue.c
servers/slapd/overlays/overlays.c
servers/slapd/overlays/pcache.c
servers/slapd/overlays/ppolicy.c
servers/slapd/overlays/rwm.c
servers/slapd/overlays/rwmmap.c
servers/slapd/overlays/syncprov.c
servers/slapd/passwd.c
servers/slapd/proto-slap.h
servers/slapd/root_dse.c
servers/slapd/sasl.c
servers/slapd/schema_init.c
servers/slapd/sl_malloc.c
servers/slapd/slap.h
servers/slapd/slapi/slapi_utils.c
servers/slapd/syncrepl.c

index 0276f3507546f67bb2b6b23a4a2ba5400ee86685..40de548d29b94b733d1c341efe2ed31178813de5 100644 (file)
@@ -88,7 +88,7 @@ typedef enum slap_aci_scope_t {
        SLAP_ACI_SCOPE_SUBTREE          = ( SLAP_ACI_SCOPE_ENTRY | SLAP_ACI_SCOPE_CHILDREN )
 } slap_aci_scope_t;
 
-static AccessControl * acl_get(
+static AccessControl * slap_acl_get(
        AccessControl *ac, int *count,
        Operation *op, Entry *e,
        AttributeDescription *desc,
@@ -96,7 +96,7 @@ static AccessControl * acl_get(
        int nmatch, regmatch_t *matches,
        AccessControlState *state );
 
-static slap_control_t acl_mask(
+static slap_control_t slap_acl_mask(
        AccessControl *ac, slap_mask_t *mask,
        Operation *op, Entry *e,
        AttributeDescription *desc,
@@ -142,7 +142,7 @@ static int aci_match_set ( struct berval *subj, Operation *op,
  * the whole attribute is assumed (all values).
  *
  * This routine loops through all access controls and calls
- * acl_mask() on each applicable access control.
+ * slap_acl_mask() on each applicable access control.
  * The loop exits when a definitive answer is reached or
  * or no more controls remain.
  *
@@ -281,7 +281,7 @@ slap_access_allowed(
                memset( matches, '\0', sizeof( matches ) );
        }
 
-       while ( ( a = acl_get( a, &count, op, e, desc, val,
+       while ( ( a = slap_acl_get( a, &count, op, e, desc, val,
                MAXREMATCHES, matches, state ) ) != NULL )
        {
                int i;
@@ -315,7 +315,7 @@ slap_access_allowed(
                }
 
 vd_access:
-               control = acl_mask( a, &mask, op,
+               control = slap_acl_mask( a, &mask, op,
                        e, desc, val, MAXREMATCHES, matches, count, state );
 
                if ( control != ACL_BREAK ) {
@@ -683,7 +683,7 @@ access_allowed_mask(
                memset( matches, '\0', sizeof(matches) );
        }
 
-       while ( ( a = acl_get( a, &count, op, e, desc, val,
+       while ( ( a = slap_acl_get( a, &count, op, e, desc, val,
                MAXREMATCHES, matches, state ) ) != NULL )
        {
                int i;
@@ -717,7 +717,7 @@ access_allowed_mask(
                }
 
 vd_access:
-               control = acl_mask( a, &mask, op,
+               control = slap_acl_mask( a, &mask, op,
                        e, desc, val, MAXREMATCHES, matches, count, state );
 
                if ( control != ACL_BREAK ) {
@@ -765,13 +765,13 @@ done:
 #endif /* SLAP_OVERLAY_ACCESS */
 
 /*
- * acl_get - return the acl applicable to entry e, attribute
+ * slap_acl_get - return the acl applicable to entry e, attribute
  * attr.  the acl returned is suitable for use in subsequent calls to
  * acl_access_allowed().
  */
 
 static AccessControl *
-acl_get(
+slap_acl_get(
        AccessControl *a,
        int                     *count,
        Operation       *op,
@@ -881,7 +881,7 @@ acl_get(
 
                        if( state && !( state->as_recorded & ACL_STATE_RECORDED_VD )) {
                                state->as_recorded |= ACL_STATE_RECORDED_VD;
-                               state->as_vd_acl = prev;
+                               state->as_vd_acl = a;
                                state->as_vd_acl_count = *count;
                                state->as_vd_access = a->acl_access;
                                state->as_vd_access_count = 1;
@@ -906,7 +906,7 @@ acl_get(
        
                                if ( a->acl_attrs[0].an_desc->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) {
                                        if (value_match( &match, desc,
-                                               desc->ad_type->sat_equality, 0,
+                                               /* desc->ad_type->sat_equality */ a->acl_attrval_mr, 0,
                                                val, &a->acl_attrval, &text ) != LDAP_SUCCESS ||
                                                        match )
                                                continue;
@@ -1353,7 +1353,7 @@ acl_mask_dnattr(
 
 
 /*
- * acl_mask - modifies mask based upon the given acl and the
+ * slap_acl_mask - modifies mask based upon the given acl and the
  * requested access to entry e, attribute attr, value val.  if val
  * is null, access to the whole attribute is assumed (all values).
  *
@@ -1362,7 +1362,7 @@ acl_mask_dnattr(
  */
 
 static slap_control_t
-acl_mask(
+slap_acl_mask(
        AccessControl           *a,
        slap_mask_t             *mask,
        Operation               *op,
@@ -1978,7 +1978,7 @@ acl_mask(
                                continue;
                        }
 
-                       /* this could be improved by changing acl_mask so that it can deal with
+                       /* this could be improved by changing slap_acl_mask so that it can deal with
                         * by clauses that return grant/deny pairs.  Right now, it does either
                         * additive or subtractive rights, but not both at the same time.  So,
                         * we need to combine the grant/deny pair into a single rights mask in
@@ -2131,7 +2131,7 @@ acl_mask(
                                continue;
                        }
 
-                       /* this could be improved by changing acl_mask so that it can deal with
+                       /* this could be improved by changing slap_acl_mask so that it can deal with
                         * by clauses that return grant/deny pairs.  Right now, it does either
                         * additive or subtractive rights, but not both at the same time.  So,
                         * we need to combine the grant/deny pair into a single rights mask in
@@ -3173,7 +3173,7 @@ dynacl_aci_parse( const char *fname, int lineno, slap_style_t sty, const char *r
        if ( sty != ACL_STYLE_REGEX && sty != ACL_STYLE_BASE ) {
                fprintf( stderr, "%s: line %d: "
                        "inappropriate style \"%s\" in \"aci\" by clause\n",
-                       fname, lineno, sty );
+                       fname, lineno, style_strings[sty] );
                return -1;
        }
 
index 01688dcb8d635096c58fff5d4587de19c62baebe..b1760206ffa8092121459363cd1a52cedb4aa798 100644 (file)
@@ -39,7 +39,7 @@
 #include "lutil.h"
 
 static const char style_base[] = "base";
-static char *style_strings[] = {
+char *style_strings[] = {
        "regex",
        "expand",
        "exact",
@@ -452,6 +452,8 @@ parse_acl(
                                        }
 
                                } else if ( strncasecmp( left, "val", 3 ) == 0 ) {
+                                       char    *mr;
+                                       
                                        if ( !BER_BVISEMPTY( &a->acl_attrval ) ) {
                                                fprintf( stderr,
                                "%s: line %d: attr val already specified in to clause.\n",
@@ -465,8 +467,34 @@ parse_acl(
                                                        fname, lineno );
                                                acl_usage();
                                        }
+
                                        ber_str2bv( right, 0, 1, &a->acl_attrval );
                                        a->acl_attrval_style = ACL_STYLE_BASE;
+
+                                       mr = strchr( left, '/' );
+                                       if ( mr != NULL ) {
+                                               mr[ 0 ] = '\0';
+                                               mr++;
+
+                                               a->acl_attrval_mr = mr_find( mr );
+                                               if ( a->acl_attrval_mr == NULL ) {
+                                                       fprintf( stderr, "%s: line %d: "
+                                                               "invalid matching rule \"%s\".\n",
+                                                               fname, lineno, mr );
+                                                       acl_usage();
+                                               }
+
+                                               if( !mr_usable_with_at( a->acl_attrval_mr, a->acl_attrs[ 0 ].an_desc->ad_type ) )
+                                               {
+                                                       fprintf( stderr, "%s: line %d: "
+                                                               "matching rule \"%s\" use "
+                                                               "with attr \"%s\" not appropriate.\n",
+                                                               fname, lineno, mr,
+                                                               a->acl_attrs[ 0 ].an_name.bv_val );
+                                                       acl_usage();
+                                               }
+                                       }
+                                       
                                        if ( style != NULL ) {
                                                if ( strcasecmp( style, "regex" ) == 0 ) {
                                                        int e = regcomp( &a->acl_attrval_re, a->acl_attrval.bv_val,
@@ -491,6 +519,8 @@ parse_acl(
                                                        } else if ( a->acl_attrs[0].an_desc->ad_type->
                                                                sat_syntax == slap_schema.si_syn_distinguishedName )
                                                        {
+                                                               struct berval   bv;
+
                                                                if ( !strcasecmp( style, "baseObject" ) ||
                                                                        !strcasecmp( style, "base" ) )
                                                                {
@@ -515,6 +545,18 @@ parse_acl(
                                                                        a->acl_attrval_style = ACL_STYLE_BASE;
                                                                }
 
+                                                               bv = a->acl_attrval;
+                                                               rc = dnNormalize( 0, NULL, NULL, &bv, &a->acl_attrval, NULL );
+                                                               if ( rc != LDAP_SUCCESS ) {
+                                                                       fprintf( stderr, 
+                                                                               "%s: line %d: unable to normalize DN \"%s\" "
+                                                                               "for attributeType \"%s\" (%d).\n",
+                                                                               fname, lineno, bv.bv_val,
+                                                                               a->acl_attrs[0].an_desc->ad_cname.bv_val, rc );
+                                                                       acl_usage();
+                                                               }
+                                                               ber_memfree( bv.bv_val );
+
                                                        } else {
                                                                fprintf( stderr, 
                                                                        "%s: line %d: unknown val.<style> \"%s\" "
@@ -525,7 +567,21 @@ parse_acl(
                                                        }
                                                }
                                        }
-                                       
+
+                                       /* Check for appropriate matching rule */
+                                       if ( a->acl_attrval_style != ACL_STYLE_REGEX ) {
+                                               if ( a->acl_attrval_mr == NULL ) {
+                                                       a->acl_attrval_mr = a->acl_attrs[ 0 ].an_desc->ad_type->sat_equality;
+                                               }
+
+                                               if ( a->acl_attrval_mr == NULL ) {
+                                                       fprintf( stderr, "%s: line %d: "
+                                                               "attr \"%s\" must have an EQUALITY matching rule.\n",
+                                                               fname, lineno, a->acl_attrs[ 0 ].an_name.bv_val );
+                                                       acl_usage();
+                                               }
+                                       }
+
                                } else {
                                        fprintf( stderr,
                                                "%s: line %d: expecting <what> got \"%s\"\n",
@@ -2053,7 +2109,7 @@ acl_usage( void )
                "<access clause> ::= access to <what> "
                                "[ by <who> <access> [ <control> ] ]+ \n"
                "<what> ::= * | [dn[.<dnstyle>]=<DN>] [filter=<filter>] [attrs=<attrlist>]\n"
-               "<attrlist> ::= <attr> [val[.<attrstyle>]=<value>] | <attr> , <attrlist>\n"
+               "<attrlist> ::= <attr> [val[/matchingRule][.<attrstyle>]=<value>] | <attr> , <attrlist>\n"
                "<attr> ::= <attrname> | entry | children\n",
                "<who> ::= [ * | anonymous | users | self | dn[.<dnstyle>]=<DN> ]\n"
                        "\t[ realanonymous | realusers | realself | realdn[.<dnstyle>]=<DN> ]\n"
index ecabe033c7e736d983d141790819b4f474c9f75a..f058c1f59672ddcda65b19638977d5d8ee64b923 100644 (file)
@@ -289,6 +289,7 @@ bdb_attr_index_unparser( void *v1, void *v2 )
                bv.bv_val = ptr;
                ber_bvarray_add( bva, &bv );
        }
+       return 0;
 }
 
 static AttributeDescription addef = { NULL, NULL, BER_BVC("default") };
index 5eef6adc1661197bd8671a0a0e45033b6a031362..1c01c2296fceb30b32c5b70b9fa2acc6a0611277 100644 (file)
@@ -17,6 +17,7 @@
 #include "portable.h"
 
 #include <stdio.h>
+#include <ac/ctype.h>
 #include <ac/string.h>
 
 #include "back-bdb.h"
@@ -66,7 +67,7 @@ static ConfigTable bdbcfg[] = {
        { "dbconfig", "DB_CONFIG setting", 1, 0, 0, ARG_MAGIC|BDB_CONFIG,
                bdb_cf_gen, "( OLcfgDbAt:1.3 NAME 'olcDbConfig' "
                        "DESC 'BerkeleyDB DB_CONFIG configuration directives' "
-                       "SYNTAX OMsDirectoryString )",NULL, NULL },
+                       "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",NULL, NULL },
        { "dbnosync", NULL, 1, 2, 0, ARG_ON_OFF|ARG_MAGIC|BDB_NOSYNC,
                bdb_cf_gen, "( OLcfgDbAt:1.4 NAME 'olcDbNoSync' "
                        "DESC 'Disable synchronous database writes' "
@@ -118,9 +119,16 @@ static ConfigTable bdbcfg[] = {
 };
 
 static ConfigOCs bdbocs[] = {
-       { "( OLcfgDbOc:1.1 "
+       {
+#ifdef BDB_HIER
+               "( OLcfgDbOc:1.2 "
+               "NAME 'olcHdbConfig' "
+               "DESC 'HDB backend configuration' "
+#else
+               "( OLcfgDbOc:1.1 "
                "NAME 'olcBdbConfig' "
                "DESC 'BDB backend configuration' "
+#endif
                "SUP olcDatabaseConfig "
                "MUST olcDbDirectory "
                "MAY ( olcDbCacheSize $ olcDbCheckpoint $ olcDbConfig $ "
@@ -485,21 +493,32 @@ bdb_cf_gen(ConfigArgs *c)
                 */
                if ((slapMode & SLAP_SERVER_MODE) && bdb->bi_txn_cp_min ) {
                        struct re_s *re = bdb->bi_txn_cp_task;
-                       if ( re )
+                       if ( re ) {
                                re->interval.tv_sec = bdb->bi_txn_cp_min * 60;
-                       else
+                       } else {
+                               if ( c->be->be_suffix == NULL || BER_BVISNULL( &c->be->be_suffix[0] ) ) {
+                                       fprintf( stderr, "%s: "
+                                               "\"checkpoint\" must occur after \"suffix\".\n",
+                                               c->log );
+                                       return 1;
+                               }
                                bdb->bi_txn_cp_task = ldap_pvt_runqueue_insert( &slapd_rq,
                                        bdb->bi_txn_cp_min * 60, bdb_checkpoint, bdb,
                                        LDAP_XSTRING(bdb_checkpoint), c->be->be_suffix[0].bv_val );
+                       }
                }
                break;
 
        case BDB_CONFIG: {
-               char *ptr = c->line + STRLENOF("dbconfig");
+               char *ptr = c->line;
                struct berval bv;
-               while (!isspace(*ptr)) ptr++;
-               while (isspace(*ptr)) ptr++;
-               
+
+               if ( c->op == SLAP_CONFIG_ADD ) {
+                       ptr += STRLENOF("dbconfig");
+                       while (!isspace(*ptr)) ptr++;
+                       while (isspace(*ptr)) ptr++;
+               }
+
                if ( bdb->bi_flags & BDB_IS_OPEN ) {
                        bdb->bi_flags |= BDB_UPD_CONFIG;
                        c->cleanup = bdb_cf_cleanup;
@@ -569,6 +588,12 @@ bdb_cf_gen(ConfigArgs *c)
                        /* Start the task as soon as we finish here. Set a long
                         * interval (10 hours) so that it only gets scheduled once.
                         */
+                       if ( c->be->be_suffix == NULL || BER_BVISNULL( &c->be->be_suffix[0] ) ) {
+                               fprintf( stderr, "%s: "
+                                       "\"index\" must occur after \"suffix\".\n",
+                                       c->log );
+                               return 1;
+                       }
                        bdb->bi_index_task = ldap_pvt_runqueue_insert( &slapd_rq, 36000,
                                bdb_online_index, c->be,
                                LDAP_XSTRING(bdb_online_index), c->be->be_suffix[0].bv_val );
index 2c2ef30e510644cf69f344d35a2e456f59292b56..89bfae0ebf311dbe778078d638d30d458f43b047 100644 (file)
@@ -670,7 +670,7 @@ hdb_dn2id(
                rc = DB_NOTFOUND;
        }
        if ( rc == 0 ) {
-               ptr = data.data + data.size - sizeof(ID);
+               ptr = (char *) data.data + data.size - sizeof(ID);
                BDB_DISK2ID( ptr, &ei->bei_id );
                ei->bei_rdn.bv_len = data.size - sizeof(diskNode) - nrlen;
                ptr = d->nrdn + nrlen + 1;
@@ -731,7 +731,7 @@ hdb_dn2id_parent(
                        rc = LDAP_OTHER;
                } else {
                        db_recno_t dkids;
-                       ptr = data.data + data.size - sizeof(ID);
+                       ptr = (char *) data.data + data.size - sizeof(ID);
                        BDB_DISK2ID( ptr, idp );
                        ei->bei_nrdn.bv_len = (d->nrdnlen[0] << 8) | d->nrdnlen[1];
                        ber_str2bv( d->nrdn, ei->bei_nrdn.bv_len, 1, &ei->bei_nrdn );
index 5a08b4db51943e257ced618e21c9a1e2758089c9..9a1e7d520c3ad626cdccc0222685cb5cbbc5a82d 100644 (file)
@@ -400,7 +400,7 @@ dn2entry_retry:
        if ( oc && !is_entry_objectclass( e, oc, 0 )) {
                Debug( LDAP_DEBUG_ACL,
                        "<= bdb_entry_get: failed to find objectClass %s\n",
-                       oc->soc_cname, 0, 0 ); 
+                       oc->soc_cname.bv_val, 0, 0 ); 
                rc = LDAP_NO_SUCH_ATTRIBUTE;
                goto return_results;
        }
index b63961f027b19353fdea6fb262178d1094685edd..a2810c1eca4fa48002dd204ad2312195e75c36a2 100644 (file)
@@ -69,6 +69,8 @@ bdb_db_init( BackendDB *be )
        ldap_pvt_thread_mutex_init( &bdb->bi_cache.lru_mutex );
        ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_dntree.bei_kids_mutex );
        ldap_pvt_thread_rdwr_init ( &bdb->bi_cache.c_rwlock );
+       ldap_pvt_thread_rdwr_init( &bdb->bi_idl_tree_rwlock );
+       ldap_pvt_thread_mutex_init( &bdb->bi_idl_tree_lrulock );
 
        be->be_private = bdb;
        be->be_cf_ocs = be->bd_info->bi_cf_ocs;
@@ -207,7 +209,10 @@ bdb_db_recover( BackendDB *be )
 #endif
 
        if( rc == ENOENT ) {
-               goto re_exit;
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_db_recover: DB environment files are missing, assuming it was "
+                       "manually recovered\n", 0, 0, 0 );
+               return 0;
        }
        else if( rc != 0 ) {
                Debug( LDAP_DEBUG_ANY,
@@ -385,8 +390,6 @@ bdb_db_open( BackendDB *be )
 
        if ( bdb->bi_idl_cache_max_size ) {
                bdb->bi_idl_tree = NULL;
-               ldap_pvt_thread_rdwr_init( &bdb->bi_idl_tree_rwlock );
-               ldap_pvt_thread_mutex_init( &bdb->bi_idl_tree_lrulock );
                bdb->bi_idl_cache_size = 0;
        }
 
@@ -630,10 +633,8 @@ bdb_db_destroy( BackendDB *be )
        ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_dntree.bei_kids_mutex );
        ldap_pvt_thread_mutex_destroy( &bdb->bi_lastid_mutex );
        ldap_pvt_thread_mutex_destroy( &bdb->bi_database_mutex );
-       if ( bdb->bi_idl_cache_max_size ) {
-               ldap_pvt_thread_rdwr_destroy( &bdb->bi_idl_tree_rwlock );
-               ldap_pvt_thread_mutex_destroy( &bdb->bi_idl_tree_lrulock );
-       }
+       ldap_pvt_thread_rdwr_destroy( &bdb->bi_idl_tree_rwlock );
+       ldap_pvt_thread_mutex_destroy( &bdb->bi_idl_tree_lrulock );
 
        ch_free( bdb );
        be->be_private = NULL;
index 830497e49fa82c2371a055d83bbd653cf49b625f..ebb8901d743efcdae741006acaffbf746b928d9d 100644 (file)
@@ -641,7 +641,7 @@ dn2entry_retry:
        for ( id = bdb_idl_first( candidates, &cursor );
                  id != NOID ; id = bdb_idl_next( candidates, &cursor ) )
        {
-               int scopeok = 0;
+               int scopeok;
 
 loop_begin:
 
@@ -731,6 +731,7 @@ fetch_entry_retry:
                 * scope while we are looking at it, and unless we're using
                 * BDB_HIER, its parents cannot be moved either.
                 */
+               scopeok = 0;
                switch( op->ors_scope ) {
                case LDAP_SCOPE_BASE:
                        /* This is always true, yes? */
index 9ef48193f706702903b0a394703d792da941a7a5..c64176b963c214c189f7dfda1a8936154048af0e 100644 (file)
@@ -35,7 +35,7 @@ static dn_id hbuf[HOLE_SIZE], *holes = hbuf;
 static unsigned nhmax = HOLE_SIZE;
 static unsigned nholes;
 
-Avlnode *index_attrs, index_dummy;
+static Avlnode *index_attrs, index_dummy;
 
 int bdb_tool_entry_open(
        BackendDB *be, int mode )
index eb272c76628fa067c9f8f489fc96d056725be588..e27e6a0255b8e9b5b57055f5a7d908f4c87e016d 100644 (file)
@@ -54,6 +54,7 @@ ldap_back_add(
 
        lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
        if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
+               lc = NULL;
                goto cleanup;
        }
 
@@ -116,6 +117,10 @@ cleanup:
                ch_free( attrs );
        }
 
+       if ( lc ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        Debug( LDAP_DEBUG_ARGS, "<== ldap_back_add(\"%s\"): %d\n",
                        op->o_req_dn.bv_val, rs->sr_err, 0 );
 
index 79b5d8e8e58383429dc844b463a984b6bbb4c82e..d33ea3c1830f28e2bfbb14e443babba5cfb3843f 100644 (file)
@@ -39,6 +39,7 @@ struct ldapconn {
        int                     lc_bound;
        int                     lc_ispriv;
        ldap_pvt_thread_mutex_t lc_mutex;
+       unsigned                lc_refcnt;
 };
 
 /*
@@ -84,6 +85,7 @@ struct ldapinfo {
 #define LDAP_BACK_AUTH_NONE            0x00U
 #define        LDAP_BACK_AUTH_NATIVE_AUTHZ     0x01U
 #define        LDAP_BACK_AUTH_OVERRIDE         0x02U
+#define        LDAP_BACK_AUTH_PRESCRIPTIVE     0x04U
 
        BerVarray       idassert_authz;
        /* end of ID assert stuff */
index ce991e476c96b8e84ebf505a1efe4d04827f0a13..9834bd1fe01da3ee5131465502d3b1c611849715 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <stdio.h>
 
+#include <ac/errno.h>
 #include <ac/socket.h>
 #include <ac/string.h>
 
@@ -101,11 +102,30 @@ done:;
 
        /* must re-insert if local DN changed as result of bind */
        if ( lc->lc_bound && !dn_match( &op->o_req_ndn, &lc->lc_local_ndn ) ) {
-               int     lerr;
+               int             lerr;
 
-               ldap_pvt_thread_mutex_lock( &li->conn_mutex );
+               /* wait for all other ops to release the connection */
+retry_lock:;
+               switch ( ldap_pvt_thread_mutex_trylock( &li->conn_mutex ) ) {
+               case LDAP_PVT_THREAD_EBUSY:
+               default:
+                       ldap_pvt_thread_yield();
+                       goto retry_lock;
+
+               case 0:
+                       if ( lc->lc_refcnt > 1 ) {
+                               ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
+                               ldap_pvt_thread_yield();
+                               goto retry_lock;
+                       }
+                       break;
+               }
+
+               assert( lc->lc_refcnt == 1 );
                lc = avl_delete( &li->conntree, (caddr_t)lc,
                                ldap_back_conn_cmp );
+               assert( lc != NULL );
+
                if ( !BER_BVISNULL( &lc->lc_local_ndn ) ) {
                        ch_free( lc->lc_local_ndn.bv_val );
                }
@@ -114,10 +134,16 @@ done:;
                        ldap_back_conn_cmp, ldap_back_conn_dup );
                ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
                if ( lerr == -1 ) {
+                       /* handle this! (e.g. wait until refcnt goes to 1...) */
                        ldap_back_conn_free( lc );
+                       lc = NULL;
                }
        }
 
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        return( rc );
 }
 
@@ -212,14 +238,30 @@ int
 ldap_back_freeconn( Operation *op, struct ldapconn *lc )
 {
        struct ldapinfo *li = (struct ldapinfo *) op->o_bd->be_private;
+       int             rc = 0;
 
-       ldap_pvt_thread_mutex_lock( &li->conn_mutex );
-       lc = avl_delete( &li->conntree, (caddr_t)lc,
-                       ldap_back_conn_cmp );
-       ldap_back_conn_free( (void *)lc );
+retry_lock:;
+       switch ( ldap_pvt_thread_mutex_trylock( &li->conn_mutex ) ) {
+       case LDAP_PVT_THREAD_EBUSY:
+       default:
+               ldap_pvt_thread_yield();
+               goto retry_lock;
+
+       case 0:
+               break;
+       }
+
+       assert( lc->lc_refcnt > 0 );
+       if ( --lc->lc_refcnt == 0 ) {
+               lc = avl_delete( &li->conntree, (caddr_t)lc,
+                               ldap_back_conn_cmp );
+               assert( lc != NULL );
+
+               ldap_back_conn_free( (void *)lc );
+       }
        ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
 
-       return 0;
+       return rc;
 }
 
 static int
@@ -332,6 +374,9 @@ retry:;
                        ldap_unbind_ext_s( ld, NULL, NULL );
                        goto error_return;
                }
+
+               /* in case Start TLS is not critical */
+               rs->sr_err = LDAP_SUCCESS;
        }
 #endif /* HAVE_TLS */
 
@@ -340,6 +385,7 @@ retry:;
                memset( *lcp, 0, sizeof( struct ldapconn ) );
        }
        (*lcp)->lc_ld = ld;
+       (*lcp)->lc_refcnt = 1;
 
 error_return:;
        if ( rs->sr_err != LDAP_SUCCESS ) {
@@ -386,13 +432,26 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
                lc_curr.lc_local_ndn = op->o_ndn;
        }
 
-       ldap_pvt_thread_mutex_lock( &li->conn_mutex );
+retry_lock:;
+       switch ( ldap_pvt_thread_mutex_trylock( &li->conn_mutex ) ) {
+       case LDAP_PVT_THREAD_EBUSY:
+       default:
+               ldap_pvt_thread_yield();
+               goto retry_lock;
+
+       case 0:
+               break;
+       }
+
        lc = (struct ldapconn *)avl_find( li->conntree, 
                        (caddr_t)&lc_curr, ldap_back_conn_cmp );
+       if ( lc != NULL ) {
+               lc->lc_refcnt++;
+       }
        ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
 
        /* Looks like we didn't get a bind. Open a new session... */
-       if ( !lc ) {
+       if ( lc == NULL ) {
                /* lc here must be NULL */
                if ( ldap_back_prepare_conn( &lc, op, rs, sendok ) != LDAP_SUCCESS ) {
                        return NULL;
@@ -421,7 +480,18 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
                lc->lc_bound = 0;
 
                /* Inserts the newly created ldapconn in the avl tree */
-               ldap_pvt_thread_mutex_lock( &li->conn_mutex );
+retry_lock2:;
+               switch ( ldap_pvt_thread_mutex_trylock( &li->conn_mutex ) ) {
+               case LDAP_PVT_THREAD_EBUSY:
+               default:
+                       ldap_pvt_thread_yield();
+                       goto retry_lock2;
+
+               case 0:
+                       break;
+               }
+
+               assert( lc->lc_refcnt == 1 );
                rs->sr_err = avl_insert( &li->conntree, (caddr_t)lc,
                        ldap_back_conn_cmp, ldap_back_conn_dup );
 
@@ -432,25 +502,53 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
                ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
 
                Debug( LDAP_DEBUG_TRACE,
-                       "=>ldap_back_getconn: conn %p inserted\n", (void *) lc, 0, 0 );
+                       "=>ldap_back_getconn: conn %p inserted (refcnt=%u)\n",
+                       (void *)lc, lc->lc_refcnt, 0 );
        
                /* Err could be -1 in case a duplicate ldapconn is inserted */
                if ( rs->sr_err != 0 ) {
                        ldap_back_conn_free( lc );
+                       rs->sr_err = LDAP_OTHER;
                        if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {
                                send_ldap_error( op, rs, LDAP_OTHER,
-                               "internal server error" );
+                                       "internal server error" );
                        }
                        return NULL;
                }
+
        } else {
                Debug( LDAP_DEBUG_TRACE,
-                       "=>ldap_back_getconn: conn %p fetched\n", (void *) lc, 0, 0 );
+                       "=>ldap_back_getconn: conn %p fetched (refcnt=%u)\n",
+                       (void *)lc, lc->lc_refcnt, 0 );
        }
        
        return lc;
 }
 
+void
+ldap_back_release_conn(
+       Operation               *op,
+       SlapReply               *rs,
+       struct ldapconn         *lc )
+{
+       struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
+
+retry_lock:;
+       switch ( ldap_pvt_thread_mutex_trylock( &li->conn_mutex ) ) {
+       case LDAP_PVT_THREAD_EBUSY:
+       default:
+               ldap_pvt_thread_yield();
+               goto retry_lock;
+
+       case 0:
+               break;
+       }
+
+       assert( lc->lc_refcnt > 0 );
+       lc->lc_refcnt--;
+       ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
+}
+
 /*
  * ldap_back_dobind
  *
@@ -464,7 +562,8 @@ ldap_back_dobind_int(
        Operation               *op,
        SlapReply               *rs,
        ldap_back_send_t        sendok,
-       int                     retries )
+       int                     retries,
+       int                     dolock )
 {      
        int             rc;
        ber_int_t       msgid;
@@ -498,7 +597,6 @@ ldap_back_dobind_int(
                 */
                if ( op->o_conn != NULL &&
                                !op->o_do_not_cache &&
-                               !be_isroot( op ) &&
                                ( BER_BVISNULL( &lc->lc_bound_ndn ) ||
                                  ( li->idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
                {
@@ -559,16 +657,34 @@ retry:;
 
                if ( rs->sr_err == LDAP_SERVER_DOWN ) {
                        if ( retries > 0 ) {
-                               ldap_unbind_ext_s( lc->lc_ld, NULL, NULL );
-                               lc->lc_ld = NULL;
-
-                               /* lc here must be the regular lc, reset and ready for init */
-                               if ( ldap_back_prepare_conn( &lc, op, rs, sendok ) != LDAP_SUCCESS ) {
-                                       return 0;
+                               if ( dolock ) {
+retry_lock:;
+                                       switch ( ldap_pvt_thread_mutex_trylock( &li->conn_mutex ) ) {
+                                       case LDAP_PVT_THREAD_EBUSY:
+                                       default:
+                                               ldap_pvt_thread_yield();
+                                               goto retry_lock;
+
+                                       case 0:
+                                               break;
+                                       }
                                }
 
-                               retries--;
-                               goto retry;
+                               assert( lc->lc_refcnt > 0 );
+                               if ( lc->lc_refcnt == 1 ) {
+                                       ldap_unbind_ext_s( lc->lc_ld, NULL, NULL );
+                                       lc->lc_ld = NULL;
+
+                                       /* lc here must be the regular lc, reset and ready for init */
+                                       rs->sr_err = ldap_back_prepare_conn( &lc, op, rs, sendok );
+                               }
+                               if ( dolock ) {
+                                       ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
+                               }
+                               if ( rs->sr_err == LDAP_SUCCESS ) {
+                                       retries--;
+                                       goto retry;
+                               }
                        }
 
                        ldap_back_freeconn( op, lc );
@@ -594,7 +710,7 @@ ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_s
        int     rc;
 
        ldap_pvt_thread_mutex_lock( &lc->lc_mutex );
-       rc = ldap_back_dobind_int( lc, op, rs, sendok, 1 );
+       rc = ldap_back_dobind_int( lc, op, rs, sendok, 1, 1 );
        ldap_pvt_thread_mutex_unlock( &lc->lc_mutex );
 
        return rc;
@@ -710,19 +826,35 @@ retry:;
 int
 ldap_back_retry( struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok )
 {
-       int     rc;
+       int             rc = 0;
+       struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
+       
+retry_lock:;
+       switch ( ldap_pvt_thread_mutex_trylock( &li->conn_mutex ) ) {
+       case LDAP_PVT_THREAD_EBUSY:
+       default:
+               ldap_pvt_thread_yield();
+               goto retry_lock;
 
-       ldap_pvt_thread_mutex_lock( &lc->lc_mutex );
-       ldap_unbind_ext_s( lc->lc_ld, NULL, NULL );
-       lc->lc_ld = NULL;
-       lc->lc_bound = 0;
+       case 0:
+               break;
+       }
 
-       /* lc here must be the regular lc, reset and ready for init */
-       rc = ldap_back_prepare_conn( &lc, op, rs, sendok );
-       if ( rc == LDAP_SUCCESS ) {
-               rc = ldap_back_dobind_int( lc, op, rs, sendok, 0 );
+       if ( lc->lc_refcnt == 1 ) {
+               ldap_pvt_thread_mutex_lock( &lc->lc_mutex );
+               ldap_unbind_ext_s( lc->lc_ld, NULL, NULL );
+               lc->lc_ld = NULL;
+               lc->lc_bound = 0;
+
+               /* lc here must be the regular lc, reset and ready for init */
+               rc = ldap_back_prepare_conn( &lc, op, rs, sendok );
+               if ( rc == LDAP_SUCCESS ) {
+                       rc = ldap_back_dobind_int( lc, op, rs, sendok, 0, 0 );
+               }
+               ldap_pvt_thread_mutex_unlock( &lc->lc_mutex );
        }
-       ldap_pvt_thread_mutex_unlock( &lc->lc_mutex );
+
+       ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
 
        return rc;
 }
@@ -773,19 +905,30 @@ ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs )
                break;
 
        default:
-               if ( li->idassert_authz ) {
+               /* NOTE: rootdn can always idassert */
+               if ( li->idassert_authz && !be_isroot( op ) ) {
                        struct berval authcDN;
 
                        if ( BER_BVISNULL( &op->o_conn->c_ndn ) ) {
                                authcDN = slap_empty_bv;
+
                        } else {
                                authcDN = op->o_conn->c_ndn;
                        }       
                        rs->sr_err = slap_sasl_matches( op, li->idassert_authz,
                                        &authcDN, &authcDN );
                        if ( rs->sr_err != LDAP_SUCCESS ) {
-                               send_ldap_result( op, rs );
-                               lc->lc_bound = 0;
+                               if ( li->idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
+                                       send_ldap_result( op, rs );
+                                       lc->lc_bound = 0;
+
+                               } else {
+                                       rs->sr_err = LDAP_SUCCESS;
+                                       binddn = slap_empty_bv;
+                                       bindcred = slap_empty_bv;
+                                       break;
+                               }
+
                                goto done;
                        }
                }
@@ -998,7 +1141,7 @@ ldap_back_proxy_authz_ctrl(
                        goto done;
                }
 
-       } else if ( li->idassert_authz ) {
+       } else if ( li->idassert_authz && !be_isroot( op ) ) {
                int             rc;
                struct berval authcDN;
 
@@ -1010,9 +1153,12 @@ ldap_back_proxy_authz_ctrl(
                rc = slap_sasl_matches( op, li->idassert_authz,
                                &authcDN, & authcDN );
                if ( rc != LDAP_SUCCESS ) {
-                       /* op->o_conn->c_ndn is not authorized
-                        * to use idassert */
-                       return rc;
+                       if ( li->idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
+                               /* op->o_conn->c_ndn is not authorized
+                                * to use idassert */
+                               return rc;
+                       }
+                       return rs->sr_err;
                }
        }
 
index a538e3d4b27cb9ea94822dcd77c7463f1ea161a6..44628d98b4c4486df1eefc9124bad6e8e1daa400 100644 (file)
@@ -44,6 +44,7 @@ ldap_back_compare(
 
        lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
        if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
+               lc = NULL;
                goto cleanup;
        }
 
@@ -70,5 +71,9 @@ retry:
 cleanup:
        (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
        
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        return rs->sr_err;
 }
index d01b8a825e85fd21d6dfaa1905903be4aedea7ec..16e1cd0a5c3674f57cedfba9ed86ac6d2db742f9 100644 (file)
@@ -362,6 +362,9 @@ ldap_back_cf_gen( ConfigArgs *c )
                        char            *ptr;
 
                        if ( li->idassert_authmethod != LDAP_AUTH_NONE ) {
+                               ber_len_t       len = bv.bv_len
+                                       + STRLENOF( "flags=override,non-prescriptive" );
+
                                switch ( li->idassert_mode ) {
                                case LDAP_BACK_IDASSERT_OTHERID:
                                case LDAP_BACK_IDASSERT_OTHERDN:
@@ -405,26 +408,34 @@ ldap_back_cf_gen( ConfigArgs *c )
                                        (void)lutil_strcopy( ptr, "authz=native" );
                                }
 
-                               if ( li->idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
-                                       ber_len_t       len = bv.bv_len + STRLENOF( "flags=override" );
+                               /* flags */
+                               if ( !BER_BVISEMPTY( &bv ) ) {
+                                       len += STRLENOF( " " );
+                               }
 
-                                       if ( !BER_BVISEMPTY( &bv ) ) {
-                                               len += STRLENOF( " " );
-                                       }
+                               bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
 
-                                       bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
+                               ptr = &bv.bv_val[ bv.bv_len ];
 
-                                       ptr = bv.bv_val + bv.bv_len;
+                               if ( !BER_BVISEMPTY( &bv ) ) {
+                                       ptr = lutil_strcopy( ptr, " " );
+                               }
 
-                                       if ( !BER_BVISEMPTY( &bv ) ) {
-                                               ptr = lutil_strcopy( ptr, " " );
-                                       }
+                               ptr = lutil_strcopy( ptr, "flags=" );
 
-                                       (void)lutil_strcopy( ptr, "flags=override" );
+                               if ( li->idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
+                                       ptr = lutil_strcopy( ptr, "prescriptive" );
+                               } else {
+                                       ptr = lutil_strcopy( ptr, "non-prescriptive" );
                                }
-                       }
 
+                               if ( li->idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
+                                       ptr = lutil_strcopy( ptr, ",override" );
+                               }
 
+                               bv.bv_len = ( ptr - bv.bv_val );
+                               /* end-of-flags */
+                       }
 
                        bindconf_unparse( &li->idassert_sb, &bc );
 
@@ -824,6 +835,12 @@ ldap_back_cf_gen( ConfigArgs *c )
                                if ( strcasecmp( c->argv[ i ], "override" ) == 0 ) {
                                        li->idassert_flags |= LDAP_BACK_AUTH_OVERRIDE;
 
+                               } else if ( strcasecmp( c->argv[ i ], "prescriptive" ) == 0 ) {
+                                       li->idassert_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE;
+
+                               } else if ( strcasecmp( c->argv[ i ], "non-prescriptive" ) == 0 ) {
+                                       li->idassert_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
+
                                } else {
                                        Debug( LDAP_DEBUG_ANY,
                                                "%s: line %d: unknown flag #%d "
@@ -951,6 +968,12 @@ ldap_back_cf_gen( ConfigArgs *c )
                                        if ( strcasecmp( flags[ j ], "override" ) == 0 ) {
                                                li->idassert_flags |= LDAP_BACK_AUTH_OVERRIDE;
 
+                                       } else if ( strcasecmp( flags[ j ], "prescriptive" ) == 0 ) {
+                                               li->idassert_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE;
+
+                                       } else if ( strcasecmp( flags[ j ], "non-prescriptive" ) == 0 ) {
+                                               li->idassert_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
+
                                        } else {
                                                fprintf( stderr, "%s: %d: "
                                                        "\"idassert-bind <args>\": "
@@ -1573,6 +1596,11 @@ retry:
                if (rs->sr_err != LDAP_SUCCESS) {
                        rs->sr_err = slap_map_api2result( rs );
                }
+
+               if ( lc != NULL ) {
+                       ldap_back_release_conn( &op2, rs, lc );
+               }
+
        } else {
        /* else just do the same as before */
                bv = (struct berval *) ch_malloc( sizeof(struct berval) );
index 3d6575be57c9153453c57d0a167635f690c72627..08c970388e975f21a5588bf117d3770f2f0a0754 100644 (file)
@@ -45,8 +45,7 @@ ldap_back_delete(
        lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
        
        if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
-               rc = -1;
-               goto cleanup;
+               return -1;
        }
 
        ctrls = op->o_ctrls;
@@ -71,5 +70,9 @@ retry:
 cleanup:
        (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
 
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        return rc;
 }
index 8fb7e44a53955b55048d6d586d52692b0acb0e87..070466ae0355ec1f3059dcfd83af98c6e37f1188 100644 (file)
@@ -68,7 +68,8 @@ ldap_back_extended(
                                op->o_ctrls = oldctrls;
                                send_ldap_result( op, rs );
                                rs->sr_text = NULL;
-                               return rs->sr_err;
+                               rc = rs->sr_err;
+                               goto done;
                        }
 
                        rc = ( *exop_table[i].extended )( op, rs );
@@ -79,6 +80,11 @@ ldap_back_extended(
                        }
                        op->o_ctrls = oldctrls;
 
+done:;
+                       if ( lc != NULL ) {
+                               ldap_back_release_conn( op, rs, lc );
+                       }
+                       
                        return rc;
                }
        }
@@ -170,5 +176,9 @@ retry:
                rc = -1;
        }
 
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        return rc;
 }
index 1b8fb45139bdf32d11f8f53cbcdc4e3fc39ee48c..49837a167f62d8b6334e5295d2b108dbac3d2916 100644 (file)
@@ -108,7 +108,7 @@ ldap_back_db_init( Backend *be )
        li->idassert_sb.sb_tls = SB_TLS_DEFAULT;
 
        /* by default, use proxyAuthz control on each operation */
-       li->idassert_flags = LDAP_BACK_AUTH_NONE;
+       li->idassert_flags = LDAP_BACK_AUTH_PRESCRIPTIVE;
 
        li->idassert_authz = NULL;
 
@@ -202,8 +202,10 @@ void
 ldap_back_conn_free( void *v_lc )
 {
        struct ldapconn *lc = v_lc;
-       
-       ldap_unbind_ext_s( lc->lc_ld, NULL, NULL );
+
+       if ( lc->lc_ld != NULL ) {      
+               ldap_unbind_ext_s( lc->lc_ld, NULL, NULL );
+       }
        if ( !BER_BVISNULL( &lc->lc_bound_ndn ) ) {
                ch_free( lc->lc_bound_ndn.bv_val );
        }
index 0936bb4e0f75463795e24873309a31964bddb411..5acd9a1aae6126862cb5e3bf9ae579b5903f8f79 100644 (file)
@@ -122,6 +122,10 @@ cleanup:;
        }
        ch_free( modv );
 
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        return rc;
 }
 
index 22554b24307742c3912b2d388bfc86832eb89d4e..437ba646e752f16fc0e6caa22d4338ac1174c69d 100644 (file)
@@ -45,7 +45,7 @@ ldap_back_modrdn(
 
        lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
        if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
-               return( -1 );
+               return -1;
        }
 
        if ( op->orr_newSup ) {
@@ -78,6 +78,10 @@ retry:
 cleanup:
        (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
 
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        return rc;
 }
 
index 8c85f507f414e1a8d1f44ba4876820f8c6412377..5f29e710a3f5299e9902211e07e0597b5364002a 100644 (file)
@@ -50,6 +50,7 @@ extern BI_entry_get_rw                ldap_back_entry_get;
 
 int ldap_back_freeconn( Operation *op, struct ldapconn *lc );
 struct ldapconn *ldap_back_getconn(struct slap_op *op, struct slap_rep *rs, ldap_back_send_t sendok);
+void ldap_back_release_conn( struct slap_op *op, struct slap_rep *rs, struct ldapconn *lc );
 int ldap_back_dobind(struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok);
 int ldap_back_retry(struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok);
 int ldap_back_map_result(SlapReply *rs);
index 19bddf422ccb4528de93ce5742557e7c31a11429..307e2dbfd6af0354ad927a79e6fe93e00d686b9d 100644 (file)
@@ -64,6 +64,7 @@ ldap_back_munge_filter(
                static struct berval
                        bv_true = BER_BVC( "(?=true)" ),
                        bv_false = BER_BVC( "(?=false)" ),
+                       bv_undefined = BER_BVC( "(?=undefined)" ),
                        bv_t = BER_BVC( "(&)" ),
                        bv_f = BER_BVC( "(|)" ),
                        bv_T = BER_BVC( "(objectClass=*)" ),
@@ -91,13 +92,18 @@ ldap_back_munge_filter(
                                newbv = &bv_F;
                        }
 
+               } else if ( strncmp( ptr, bv_undefined.bv_val, bv_undefined.bv_len ) == 0 )
+               {
+                       oldbv = &bv_undefined;
+                       newbv = &bv_F;
+
                } else {
                        gotit = 0;
                        goto done;
                }
 
                oldfilter = *filter;
-               if ( !( li->flags & LDAP_BACK_F_SUPPORT_T_F ) ) {
+               if ( newbv->bv_len > oldbv->bv_len ) {
                        filter->bv_len += newbv->bv_len - oldbv->bv_len;
                        if ( filter->bv_val == op->ors_filterstr.bv_val ) {
                                filter->bv_val = op->o_tmpalloc( filter->bv_len + 1,
@@ -151,7 +157,7 @@ ldap_back_search(
        LDAPControl     **ctrls = NULL;
 
        lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
-       if ( !lc ) {
+       if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                return rs->sr_err;
        }
 
@@ -159,9 +165,6 @@ ldap_back_search(
         * FIXME: in case of values return filter, we might want
         * to map attrs and maybe rewrite value
         */
-       if ( !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
-               return rs->sr_err;
-       }
 
        /* should we check return values? */
        if ( op->ors_deref != -1 ) {
@@ -280,7 +283,7 @@ fail:;
 
                        e = ldap_first_entry( lc->lc_ld, res );
                        rc = ldap_build_entry( op, e, &ent, &bdn );
-                      if ( rc == LDAP_SUCCESS ) {
+                       if ( rc == LDAP_SUCCESS ) {
                                rs->sr_entry = &ent;
                                rs->sr_attrs = op->ors_attrs;
                                rs->sr_operational_attrs = NULL;
@@ -435,6 +438,10 @@ finish:;
                ch_free( attrs );
        }
 
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        return rc;
 }
 
@@ -716,6 +723,10 @@ cleanup:
                ch_free( filter );
        }
 
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, &rs, lc );
+       }
+
        return rc;
 }
 
index e93dba2c89035feab94fad81b9b1507f2ac005cb..aa699342b6aa97f41f4dd4514d50bf38146d7316 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <stdio.h>
 
+#include <ac/errno.h>
 #include <ac/socket.h>
 #include <ac/string.h>
 
@@ -47,14 +48,26 @@ ldap_back_conn_destroy(
        lc_curr.lc_conn = conn;
        lc_curr.lc_local_ndn = conn->c_ndn;
        
-       ldap_pvt_thread_mutex_lock( &li->conn_mutex );
+retry_lock:;
+       switch ( ldap_pvt_thread_mutex_trylock( &li->conn_mutex ) ) {
+       case LDAP_PVT_THREAD_EBUSY:
+       default:
+               ldap_pvt_thread_yield();
+               goto retry_lock;
+
+       case 0:
+               break;
+       }
+
        lc = avl_delete( &li->conntree, (caddr_t)&lc_curr, ldap_back_conn_cmp );
        ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
 
        if ( lc ) {
                Debug( LDAP_DEBUG_TRACE,
-                       "=>ldap_back_conn_destroy: destroying conn %ld\n",
-                       lc->lc_conn->c_connid, 0, 0 );
+                       "=>ldap_back_conn_destroy: destroying conn %ld (refcnt=%u)\n",
+                       lc->lc_conn->c_connid, lc->lc_refcnt, 0 );
+
+               assert( lc->lc_refcnt == 0 );
 
                /*
                 * Needs a test because the handler may be corrupted,
index 3fae53e80743c6ea307842c0d87047b827191180..f8da8e07e841de2366aa7a6004a4e6851594a8e2 100644 (file)
@@ -118,7 +118,7 @@ int ldbm_back_entry_get(
        if ( oc && !is_entry_objectclass( e, oc, 0 )) {
                Debug( LDAP_DEBUG_ACL,
                        "<= ldbm_back_entry_get: failed to find objectClass %s\n",
-                       oc->soc_cname, 0, 0 ); 
+                       oc->soc_cname.bv_val, 0, 0 ); 
                rc = LDAP_NO_SUCH_ATTRIBUTE;
                goto return_results;
        }
index a59fe576ebda46207f1847634f53095cbc394193..a9550a54156e177ed94c37b84b281a1fbe2cd983 100644 (file)
@@ -144,21 +144,18 @@ static char * slurp_file(int fd) {
        return entry;
 }
 
-static int spew_file(int fd, char * spew) {
-       int written = 0;
+static int spew_file(int fd, char * spew, int len) {
        int writeres = 0;
-       int len = strlen(spew);
-       char * spewptr = spew;
        
-       while(written < len) {
-               writeres = write(fd, spewptr, len - written);
+       while(len > 0) {
+               writeres = write(fd, spew, len);
                if(writeres == -1) {
                        perror("could not spew write");
                        return -1;
                }
                else {
-                       spewptr += writeres;
-                       written += writeres;
+                       spew += writeres;
+                       len -= writeres;
                }
        }
        return writeres;
@@ -171,7 +168,7 @@ static int spew_entry(Entry * e, struct berval * path) {
        int entry_length;
        char * entry_as_string;
 
-       openres = open(path->bv_val, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+       openres = open(path->bv_val, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR | S_IWUSR);
        if(openres == -1) {
                if(errno == ENOENT)
                        rs = LDAP_NO_SUCH_OBJECT;
@@ -204,7 +201,7 @@ static int spew_entry(Entry * e, struct berval * path) {
                        close(openres);
                }
                else {
-                       spew_res = spew_file(openres, entry_as_string);
+                       spew_res = spew_file(openres, entry_as_string, entry_length);
                        close(openres);
                        if(spew_res == -1)
                                rs = LDAP_UNWILLING_TO_PERFORM;
index a17fdbb24ac04c963888c3efbc6b1639338fc225..31b0fcb59a108d8db161060223c44c7ea31b6fde 100644 (file)
@@ -68,7 +68,7 @@ meta_back_add( Operation *op, SlapReply *rs )
 
        if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
                send_ldap_result( op, rs );
-               return rs->sr_err;
+               goto done;
        }
 
        /* Count number of attributes in entry ( +1 ) */
@@ -187,6 +187,11 @@ retry:;
                BER_BVZERO( &mdn );
        }
 
-       return meta_back_op_result( mc, op, rs, candidate );
+       (void)meta_back_op_result( mc, op, rs, candidate );
+
+done:;
+       meta_back_release_conn( op, mc );
+
+       return rs->sr_err;
 }
 
index 620bb93e14c96ef7976c3e43c5cb6adff728166e..c3c23adadb38afd8a4eb5acdb3bac3d120a9f441 100644 (file)
@@ -177,6 +177,7 @@ typedef struct metasingleconn_t {
 typedef struct metaconn_t {
        struct slap_conn        *mc_conn;
        ldap_pvt_thread_mutex_t mc_mutex;
+       unsigned                mc_refcnt;
        
        /*
         * means that the connection is bound; 
@@ -186,7 +187,10 @@ typedef struct metaconn_t {
 #define META_BOUND_NONE                (-1)
 #define META_BOUND_ALL         (-2)
        /* supersedes the connection stuff */
-       metasingleconn_t        *mc_conns;
+       metasingleconn_t        mc_conns[ 1 ];
+       /* NOTE: mc_conns must be last, because
+        * the required number of conns is malloc'ed
+        * in one block with the metaconn_t structure */
 } metaconn_t;
 
 typedef struct metatarget_t {
@@ -222,6 +226,11 @@ typedef struct metadncache_t {
        long int                ttl;  /* seconds; 0: no cache, -1: no expiry */
 } metadncache_t;
 
+typedef struct metacandidates_t {
+       int                     mc_ntargets;
+       SlapReply               *mc_candidates;
+} metacandidates_t;
+
 typedef struct metainfo_t {
        int                     mi_ntargets;
        int                     mi_defaulttarget;
@@ -230,7 +239,7 @@ typedef struct metainfo_t {
        int                     mi_nretries;
 
        metatarget_t            *mi_targets;
-       SlapReply               *mi_candidates;
+       metacandidates_t        *mi_candidates;
 
        metadncache_t           mi_cache;
        
@@ -238,16 +247,10 @@ typedef struct metainfo_t {
        Avlnode                 *mi_conntree;
 
        unsigned                flags;
-#if 0
-/* 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_PROPAGATE_TLS      0x04U
-#define LDAP_BACK_F_TLS_CRITICAL       0x08U
-#define LDAP_BACK_F_TLS_MASK           (LDAP_BACK_F_USE_TLS|LDAP_BACK_F_PROPAGATE_TLS|LDAP_BACK_F_TLS_CRITICAL)
-#define LDAP_BACK_F_CHASE_REFERRALS    0x10U
-#endif
+/* uses flags as defined in <back-ldap/back-ldap.h> */
+#define        META_BACK_F_ONERR_STOP  0x00010000U
+#define        META_BACK_ONERR_STOP(mi)        ( (mi)->flags & META_BACK_F_ONERR_STOP )
+#define        META_BACK_ONERR_CONTINUE(mi)    ( !META_BACK_ONERR_CONTINUE( (mi) ) )
 
        int                     mi_version;
 } metainfo_t;
@@ -268,6 +271,11 @@ meta_back_getconn(
        int                     *candidate,
        ldap_back_send_t        sendok );
 
+extern void
+meta_back_release_conn(
+               Operation               *op,
+       metaconn_t              *mc );
+
 extern int
 meta_back_retry(
        Operation               *op,
@@ -277,7 +285,8 @@ meta_back_retry(
        ldap_back_send_t        sendok );
 
 extern void
-meta_back_conn_free( metaconn_t *mc );
+meta_back_conn_free(
+       metaconn_t              *mc );
 
 extern int
 meta_back_init_one_conn(
@@ -301,7 +310,8 @@ meta_back_single_dobind(
        metaconn_t              *msc,
        int                     candidate,
        ldap_back_send_t        sendok,
-       int                     retries );
+       int                     retries,
+       int                     dolock );
 
 extern int
 meta_back_op_result(
index 120959699f61ca10732d2c937179a78931d39bee..a3d67e4595c7dd02c1225d6996eed9dab7cc2302 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <stdio.h>
 
+#include <ac/errno.h>
 #include <ac/socket.h>
 #include <ac/string.h>
 
@@ -46,7 +47,7 @@ int
 meta_back_bind( Operation *op, SlapReply *rs )
 {
        metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
-       metaconn_t      *mc;
+       metaconn_t      *mc = NULL;
 
        int             rc = LDAP_OTHER,
                        i, gotit = 0, isroot = 0;
@@ -137,6 +138,8 @@ meta_back_bind( Operation *op, SlapReply *rs )
                mc->mc_auth_target = META_BOUND_ALL;
        }
 
+       meta_back_release_conn( op, mc );
+
        /*
         * rc is LDAP_SUCCESS if at least one bind succeeded,
         * err is the last error that occurred during a bind;
@@ -257,13 +260,33 @@ retry:;
 
                        rc = slap_map_api2result( rs );
                        if ( rs->sr_err == LDAP_UNAVAILABLE && nretries != META_RETRY_NEVER ) {
-                               ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
-                               msc->msc_ld = NULL;
-                               msc->msc_bound = 0;
+retry_lock:;
+                               switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
+                               case LDAP_PVT_THREAD_EBUSY:
+                               default:
+                                       ldap_pvt_thread_yield();
+                                       goto retry_lock;
+
+                               case 0:
+                                       break;
+                               }
+
+                               if ( mc->mc_refcnt == 1 ) {
+                                       ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
+                                       msc->msc_ld = NULL;
+                                       msc->msc_bound = 0;
+
+                                       /* mc here must be the regular mc, reset and ready for init */
+                                       rc = meta_back_init_one_conn( op, rs, mt, msc,
+                                                       LDAP_BACK_DONTSEND );
+
+                               } else {
+                                       /* can't do anything about it */
+                                       rc = 0;
+                               }
+
+                               ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
 
-                               /* mc here must be the regular mc, reset and ready for init */
-                               rc = meta_back_init_one_conn( op, rs, mt, msc,
-                                               LDAP_BACK_DONTSEND );
                                if ( rc ) {
                                        if ( nretries > 0 ) {
                                                nretries--;
@@ -323,7 +346,8 @@ meta_back_single_dobind(
        metaconn_t              *mc,
        int                     candidate,
        ldap_back_send_t        sendok,
-       int                     nretries )
+       int                     nretries,
+       int                     dolock )
 {
        metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
        metatarget_t            *mt = &mi->mi_targets[ candidate ];
@@ -406,12 +430,36 @@ retry:;
 
                        rc = slap_map_api2result( rs );
                        if ( rc == LDAP_UNAVAILABLE && nretries != META_RETRY_NEVER ) {
-                               ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
-                               msc->msc_ld = NULL;
-                               msc->msc_bound = 0;
+                               if ( dolock ) {
+retry_lock:;
+                                       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
+                                       case LDAP_PVT_THREAD_EBUSY:
+                                       default:
+                                               ldap_pvt_thread_yield();
+                                               goto retry_lock;
+       
+                                       case 0:
+                                               break;
+                                       }
+                               }
+
+                               if ( mc->mc_refcnt == 1 ) {
+                                       ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
+                                       msc->msc_ld = NULL;
+                                       msc->msc_bound = 0;
 
-                               /* mc here must be the regular mc, reset and ready for init */
-                               rc = meta_back_init_one_conn( op, rs, mt, msc, LDAP_BACK_DONTSEND );
+                                       /* mc here must be the regular mc, reset and ready for init */
+                                       rc = meta_back_init_one_conn( op, rs, mt, msc, LDAP_BACK_DONTSEND );
+                               
+
+                               } else {
+                                       /* can't do anything about it */
+                                       rc = LDAP_UNAVAILABLE;
+                               }
+
+                               if ( dolock ) {
+                                       ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
+                               }
 
                                if ( rc == LDAP_SUCCESS ) {
                                        ldap_pvt_thread_yield();
@@ -501,7 +549,7 @@ meta_back_dobind(
                }
 
                rc = meta_back_single_dobind( op, rs, mc, i,
-                               LDAP_BACK_DONTSEND, mt->mt_nretries );
+                               LDAP_BACK_DONTSEND, mt->mt_nretries, 1 );
                if ( rc != LDAP_SUCCESS ) {
                        rs->sr_err = slap_map_api2result( rs );
 
@@ -535,11 +583,15 @@ done:;
                "%s meta_back_dobind: conn=%ld bound=%d\n",
                op->o_log_prefix, mc->mc_conn->c_connid, bound );
 
-       if ( bound == 0 && ( sendok & LDAP_BACK_SENDERR ) ) {
-               if ( rs->sr_err == LDAP_SUCCESS ) {
-                       rs->sr_err = LDAP_BUSY;
+       if ( bound == 0 ) {
+               meta_back_release_conn( op, mc );
+
+               if ( sendok & LDAP_BACK_SENDERR ) {
+                       if ( rs->sr_err == LDAP_SUCCESS ) {
+                               rs->sr_err = LDAP_BUSY;
+                       }
+                       send_ldap_result( op, rs );
                }
-               send_ldap_result( op, rs );
        }
 
        return( bound > 0 );
index df3e9f63a5f9c4fa9500f90fbea797536bdd9091..76023a8837f039a01dad55dc764f86ab277fb0f7 100644 (file)
@@ -103,9 +103,10 @@ meta_back_is_candidate_unique(
 /*
  * meta_back_select_unique_candidate
  *
- * returns the index of the candidate in case it is unique, otherwise -1
- * Note: dn MUST be normalized.
- * Note: if defined, the default candidate is returned in case of no match.
+ * returns the index of the candidate in case it is unique, otherwise
+ * META_TARGET_NONE if none matches, or
+ * META_TARGET_MULTIPLE if more than one matches
+ * Note: ndn MUST be normalized.
  */
 int
 meta_back_select_unique_candidate(
index 77701d154e2277e86f56f315dddd0c303cfe822c..42a99e59b7aff48929f55c2aa108a93a9c79295a 100644 (file)
@@ -35,7 +35,7 @@ int
 meta_back_compare( Operation *op, SlapReply *rs )
 {
        metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
-       metaconn_t              *mc;
+       metaconn_t              *mc = NULL;
        char                    *match = NULL,
                                *err = NULL;
        struct berval           mmatch = BER_BVNULL;
@@ -58,7 +58,9 @@ meta_back_compare( Operation *op, SlapReply *rs )
        
        msgid = ch_calloc( sizeof( int ), mi->mi_ntargets );
        if ( msgid == NULL ) {
-               return -1;
+               send_ldap_error( op, rs, LDAP_OTHER, NULL );
+               rc = LDAP_OTHER;
+               goto done;
        }
 
        /*
@@ -314,7 +316,10 @@ finish:;
        if ( msgid ) {
                free( msgid );
        }
-       
+
+done:;
+       meta_back_release_conn( op, mc );
+
        return rc;
 }
 
index 8457cf8510e76f5698bb8c57a2f5dbc5e2ed6b1f..62fcd5f071eeb5d7c33b0f436ae577d1cd473835 100644 (file)
@@ -351,14 +351,33 @@ meta_back_db_config(
                
        /* save bind creds for referral rebinds? */
        } else if ( strcasecmp( argv[ 0 ], "rebind-as-user" ) == 0 ) {
-               if (argc != 1) {
+               if ( argc > 2 ) {
                        fprintf( stderr,
-       "%s: line %d: rebind-as-user takes no arguments\n",
+       "%s: line %d: \"rebind-as-user {NO|yes}\" takes 1 argument.\n",
                            fname, lineno );
                        return( 1 );
                }
 
-               mi->flags |= LDAP_BACK_F_SAVECRED;
+               if ( argc == 1 ) {
+                       fprintf( stderr,
+       "%s: line %d: deprecated use of \"rebind-as-user {NO|yes}\" with no arguments.\n",
+                           fname, lineno );
+                       mi->flags |= LDAP_BACK_F_SAVECRED;
+
+               } else {
+                       if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+                               mi->flags &= ~LDAP_BACK_F_SAVECRED;
+
+                       } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+                               mi->flags |= LDAP_BACK_F_SAVECRED;
+
+                       } else {
+                               fprintf( stderr,
+       "%s: line %d: \"rebind-as-user {NO|yes}\" unknown argument \"%s\".\n",
+                                   fname, lineno, argv[ 1 ] );
+                               return 1;
+                       }
+               }
 
        } else if ( strcasecmp( argv[ 0 ], "chase-referrals" ) == 0 ) {
                unsigned        *flagsp = mi->mi_ntargets ?
@@ -381,7 +400,7 @@ meta_back_db_config(
 
                } else {
                        fprintf( stderr,
-               "%s: line %d: \"chase-referrals {yes|no}\": unknown argument \"%s\".\n",
+               "%s: line %d: \"chase-referrals {YES|no}\": unknown argument \"%s\".\n",
                                        fname, lineno, argv[ 1 ] );
                        return( 1 );
                }
@@ -430,7 +449,7 @@ meta_back_db_config(
 
                if ( argc != 2 ) {
                        fprintf( stderr,
-               "%s: line %d: \"t-f-support {no|yes|discover}\" needs 1 argument.\n",
+               "%s: line %d: \"t-f-support {NO|yes|discover}\" needs 1 argument.\n",
                                        fname, lineno );
                        return( 1 );
                }
@@ -451,6 +470,28 @@ meta_back_db_config(
                        return 1;
                }
 
+       /* onerr? */
+       } else if ( strcasecmp( argv[ 0 ], "onerr" ) == 0 ) {
+               if ( argc != 2 ) {
+                       fprintf( stderr,
+       "%s: line %d: \"onerr {CONTINUE|stop}\" takes 1 argument\n",
+                           fname, lineno );
+                       return( 1 );
+               }
+
+               if ( strcasecmp( argv[ 1 ], "continue" ) == 0 ) {
+                       mi->flags &= ~META_BACK_F_ONERR_STOP;
+
+               } else if ( strcasecmp( argv[ 1 ], "stop" ) == 0 ) {
+                       mi->flags |= META_BACK_F_ONERR_STOP;
+
+               } else {
+                       fprintf( stderr,
+       "%s: line %d: \"onerr {CONTINUE|stop}\": invalid arg \"%s\".\n",
+                               fname, lineno, argv[ 1 ] );
+                       return 1;
+               }
+
        /* name to use as pseudo-root dn */
        } else if ( strcasecmp( argv[ 0 ], "pseudorootdn" ) == 0 ) {
                int             i = mi->mi_ntargets - 1;
index 587bd15d98bc38ed5f388d5ceb6d07eea0c5865f..1379d8c3a1b10527d171b71715b111a097a6be5b 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <stdio.h>
 
+#include <ac/errno.h>
 #include <ac/socket.h>
 #include <ac/string.h>
 
@@ -129,15 +130,13 @@ metaconn_alloc(
 
        assert( ntargets > 0 );
 
-       /* malloc once only; leave an extra one for one-past-end */
+       /* malloc all in one */
        mc = ( metaconn_t * )ch_malloc( sizeof( metaconn_t )
                        + sizeof( metasingleconn_t ) * ntargets );
        if ( mc == NULL ) {
                return NULL;
        }
 
-       mc->mc_conns = ( metasingleconn_t * )&mc[ 1 ];
-
        for ( i = 0; i < ntargets; i++ ) {
                mc->mc_conns[ i ].msc_ld = NULL;
                BER_BVZERO( &mc->mc_conns[ i ].msc_bound_ndn );
@@ -148,6 +147,7 @@ metaconn_alloc(
 
        mc->mc_auth_target = META_BOUND_NONE;
        ldap_pvt_thread_mutex_init( &mc->mc_mutex );
+       mc->mc_refcnt = 1;
 
        return mc;
 }
@@ -157,19 +157,45 @@ metaconn_alloc(
  *
  * clears a metaconn
  */
+
 void
 meta_back_conn_free(
        metaconn_t      *mc )
 {
-       if ( mc == NULL ) {
-               return;
-       }
+       assert( mc != NULL );
+       assert( mc->mc_refcnt == 0 );
 
        ldap_pvt_thread_mutex_destroy( &mc->mc_mutex );
-       
        free( mc );
 }
 
+static void
+meta_back_freeconn(
+       Operation       *op,
+       metaconn_t      *mc )
+{
+       metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
+
+       assert( mc != NULL );
+
+retry_lock:;
+       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
+       case LDAP_PVT_THREAD_EBUSY:
+       default:
+               ldap_pvt_thread_yield();
+               goto retry_lock;
+
+       case 0:
+               break;
+       }
+
+       if ( --mc->mc_refcnt == 0 ) {
+               meta_back_conn_free( mc );
+       }
+
+       ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
+}
+
 /*
  * meta_back_init_one_conn
  * 
@@ -382,24 +408,41 @@ meta_back_retry(
 {
        metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
        metatarget_t            *mt = &mi->mi_targets[ candidate ];
-       int                     rc;
+       int                     rc = LDAP_UNAVAILABLE;
        metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
 
-       ldap_pvt_thread_mutex_lock( &mc->mc_mutex );
+retry_lock:;
+       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
+       case LDAP_PVT_THREAD_EBUSY:
+       default:
+               ldap_pvt_thread_yield();
+               goto retry_lock;
+
+       case 0:
+               break;
+       }
 
-       ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
-        msc->msc_ld = NULL;
-        msc->msc_bound = 0;
+       assert( mc->mc_refcnt > 0 );
 
-        /* mc here must be the regular mc, reset and ready for init */
-        rc = meta_back_init_one_conn( op, rs, mt, msc, sendok );
+       if ( mc->mc_refcnt == 1 ) {
+               ldap_pvt_thread_mutex_lock( &mc->mc_mutex );
 
-       if ( rc == LDAP_SUCCESS ) {
-               rc = meta_back_single_dobind( op, rs, mc, candidate,
-                               sendok, mt->mt_nretries );
-        }
+               ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
+               msc->msc_ld = NULL;
+               msc->msc_bound = 0;
 
-       ldap_pvt_thread_mutex_unlock( &mc->mc_mutex );
+               /* mc here must be the regular mc, reset and ready for init */
+               rc = meta_back_init_one_conn( op, rs, mt, msc, sendok );
+
+               if ( rc == LDAP_SUCCESS ) {
+                       rc = meta_back_single_dobind( op, rs, mc, candidate,
+                                       sendok, mt->mt_nretries, 0 );
+               }
+
+               ldap_pvt_thread_mutex_unlock( &mc->mc_mutex );
+       }
+
+       ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
 
        return rc == LDAP_SUCCESS ? 1 : 0;
 }
@@ -512,39 +555,59 @@ meta_back_get_candidate(
 }
 
 static void
-meta_back_candidate_keyfree(
+meta_back_candidates_keyfree(
        void            *key,
        void            *data )
 {
+       metacandidates_t        *mc = (metacandidates_t *)data;
+
+       ber_memfree_x( mc->mc_candidates, NULL );
        ber_memfree_x( data, NULL );
 }
 
 SlapReply *
 meta_back_candidates_get( Operation *op )
 {
-       metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
-       void            *data = NULL;
+       metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
+       metacandidates_t        *mc;
+       SlapReply               *rs;
 
        if ( op->o_threadctx ) {
+               void            *data = NULL;
+
                ldap_pvt_thread_pool_getkey( op->o_threadctx,
-                               meta_back_candidate_keyfree, &data, NULL );
+                               meta_back_candidates_keyfree, &data, NULL );
+               mc = (metacandidates_t *)data;
+
        } else {
-               data = (void *)mi->mi_candidates;
+               mc = mi->mi_candidates;
        }
 
-       if ( data == NULL ) {
-               data = ber_memalloc( sizeof( SlapReply ) * mi->mi_ntargets );
+       if ( mc == NULL ) {
+               mc = ch_calloc( sizeof( metacandidates_t ), 1 );
+               mc->mc_ntargets = mi->mi_ntargets;
+               mc->mc_candidates = ch_calloc( sizeof( SlapReply ), mc->mc_ntargets );
                if ( op->o_threadctx ) {
+                       void            *data = NULL;
+
+                       data = (void *)mc;
                        ldap_pvt_thread_pool_setkey( op->o_threadctx,
-                                       meta_back_candidate_keyfree, data,
-                                       meta_back_candidate_keyfree );
+                                       meta_back_candidates_keyfree, data,
+                                       meta_back_candidates_keyfree );
 
                } else {
-                       mi->mi_candidates = (SlapReply *)data;
+                       mi->mi_candidates = mc;
                }
+
+       } else if ( mc->mc_ntargets < mi->mi_ntargets ) {
+               /* NOTE: in the future, may want to allow back-config
+                * to add/remove targets from back-meta... */
+               mc->mc_ntargets = mi->mi_ntargets;
+               mc->mc_candidates = ch_realloc( mc->mc_candidates,
+                               sizeof( SlapReply ) * mc->mc_ntargets );
        }
 
-       return (SlapReply *)data;
+       return mc->mc_candidates;
 }
 
 /*
@@ -588,7 +651,8 @@ meta_back_getconn(
        ldap_back_send_t        sendok )
 {
        metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
-       metaconn_t      *mc, mc_curr;
+       metaconn_t      *mc = NULL,
+                       mc_curr = { 0 };
        int             cached = META_TARGET_NONE,
                        i = META_TARGET_NONE,
                        err = LDAP_SUCCESS,
@@ -606,9 +670,21 @@ meta_back_getconn(
 
        /* Searches for a metaconn in the avl tree */
        mc_curr.mc_conn = op->o_conn;
-       ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
+retry_lock:;
+       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
+       case LDAP_PVT_THREAD_EBUSY:
+       default:
+               ldap_pvt_thread_yield();
+               goto retry_lock;
+
+       case 0:
+               break;
+       }
        mc = (metaconn_t *)avl_find( mi->mi_conntree, 
                (caddr_t)&mc_curr, meta_back_conn_cmp );
+       if ( mc ) {
+               mc->mc_refcnt++;
+       }
        ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
 
        switch ( op->o_tag ) {
@@ -657,7 +733,7 @@ meta_back_getconn(
        if ( op_type == META_OP_REQUIRE_ALL ) {
 
                /* Looks like we didn't get a bind. Open a new session... */
-               if ( !mc ) {
+               if ( mc == NULL ) {
                        mc = metaconn_alloc( op );
                        mc->mc_conn = op->o_conn;
                        new_conn = 1;
@@ -687,6 +763,30 @@ meta_back_getconn(
                                continue;
                        }
                }
+
+               if ( ncandidates == 0 ) {
+                       if ( new_conn ) {
+                               meta_back_freeconn( op, mc );
+
+                       } else {
+                               meta_back_release_conn( op, mc );
+                       }
+
+                       rs->sr_err = LDAP_NO_SUCH_OBJECT;
+                       rs->sr_text = "Unable to select valid candidates";
+
+                       if ( sendok & LDAP_BACK_SENDERR ) {
+                               if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
+                                       rs->sr_matched = op->o_bd->be_suffix[ 0 ].bv_val;
+                               }
+                               send_ldap_result( op, rs );
+                               rs->sr_text = NULL;
+                               rs->sr_matched = NULL;
+                       }
+
+                       return NULL;
+               }
+
                goto done;
        }
        
@@ -717,8 +817,12 @@ meta_back_getconn(
        
                        if ( rs->sr_err != LDAP_SUCCESS ) {
                                if ( sendok & LDAP_BACK_SENDERR ) {
+                                       if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
+                                               rs->sr_matched = op->o_bd->be_suffix[ 0 ].bv_val;
+                                       }
                                        send_ldap_result( op, rs );
                                        rs->sr_text = NULL;
+                                       rs->sr_matched = NULL;
                                }
                                return NULL;
                        }
@@ -739,18 +843,34 @@ meta_back_getconn(
        "==>meta_back_getconn: got target %d for ndn=\"%s\" from cache\n",
                                i, op->o_req_ndn.bv_val, 0 );
 
-               /* Retries searching for a metaconn in the avl tree */
-               mc_curr.mc_conn = op->o_conn;
-               ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
-               mc = (metaconn_t *)avl_find( mi->mi_conntree, 
-                       (caddr_t)&mc_curr, meta_back_conn_cmp );
-               ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
+               if ( mc == NULL ) {
+                       /* Retries searching for a metaconn in the avl tree
+                        * the reason is that the connection might have been
+                        * created by meta_back_get_candidate() */
+                       mc_curr.mc_conn = op->o_conn;
+retry_lock2:;
+                       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
+                       case LDAP_PVT_THREAD_EBUSY:
+                       default:
+                               ldap_pvt_thread_yield();
+                               goto retry_lock2;
+
+                       case 0:
+                               break;
+                       }
+                       mc = (metaconn_t *)avl_find( mi->mi_conntree, 
+                               (caddr_t)&mc_curr, meta_back_conn_cmp );
+                       if ( mc != NULL ) {
+                               mc->mc_refcnt++;
+                       }
+                       ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
 
-               /* Looks like we didn't get a bind. Open a new session... */
-               if ( !mc ) {
-                       mc = metaconn_alloc( op );
-                       mc->mc_conn = op->o_conn;
-                       new_conn = 1;
+                       /* Looks like we didn't get a bind. Open a new session... */
+                       if ( mc == NULL ) {
+                               mc = metaconn_alloc( op );
+                               mc->mc_conn = op->o_conn;
+                               new_conn = 1;
+                       }
                }
 
                /*
@@ -765,12 +885,7 @@ meta_back_getconn(
                 */
                err = meta_back_init_one_conn( op, rs, &mi->mi_targets[ i ],
                                &mc->mc_conns[ i ], sendok );
-               if ( err == LDAP_SUCCESS ) {
-                       candidates[ i ].sr_tag = META_CANDIDATE;
-                       ncandidates++;
-
-               } else {
-               
+               if ( err != LDAP_SUCCESS ) {
                        /*
                         * FIXME: in case one target cannot
                         * be init'd, should the other ones
@@ -778,12 +893,18 @@ meta_back_getconn(
                         */
                        candidates[ i ].sr_tag = META_NOT_CANDIDATE;
                        if ( new_conn ) {
-                               ( void )meta_clear_one_candidate( &mc->mc_conns[ i ] );
-                               meta_back_conn_free( mc );
+                               (void)meta_clear_one_candidate( &mc->mc_conns[ i ] );
+                               meta_back_freeconn( op, mc );
+
+                       } else {
+                               meta_back_release_conn( op, mc );
                        }
                        return NULL;
                }
 
+               candidates[ i ].sr_tag = META_CANDIDATE;
+               ncandidates++;
+
                if ( candidate ) {
                        *candidate = i;
                }
@@ -794,7 +915,7 @@ meta_back_getconn(
        } else {
 
                /* Looks like we didn't get a bind. Open a new session... */
-               if ( !mc ) {
+               if ( mc == NULL ) {
                        mc = metaconn_alloc( op );
                        mc->mc_conn = op->o_conn;
                        new_conn = 1;
@@ -849,15 +970,22 @@ meta_back_getconn(
 
                if ( ncandidates == 0 ) {
                        if ( new_conn ) {
-                               meta_back_conn_free( mc );
+                               meta_back_freeconn( op, mc );
+
+                       } else {
+                               meta_back_release_conn( op, mc );
                        }
 
                        rs->sr_err = LDAP_NO_SUCH_OBJECT;
                        rs->sr_text = "Unable to select valid candidates";
 
                        if ( sendok & LDAP_BACK_SENDERR ) {
+                               if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
+                                       rs->sr_matched = op->o_bd->be_suffix[ 0 ].bv_val;
+                               }
                                send_ldap_result( op, rs );
                                rs->sr_text = NULL;
+                               rs->sr_matched = NULL;
                        }
 
                        return NULL;
@@ -874,7 +1002,16 @@ done:;
                /*
                 * Inserts the newly created metaconn in the avl tree
                 */
-               ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
+retry_lock3:;
+               switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
+               case LDAP_PVT_THREAD_EBUSY:
+               default:
+                       ldap_pvt_thread_yield();
+                       goto retry_lock3;
+
+               case 0:
+                       break;
+               }
                err = avl_insert( &mi->mi_conntree, ( caddr_t )mc,
                                meta_back_conn_cmp, meta_back_conn_dup );
 
@@ -886,20 +1023,18 @@ done:;
 
                /*
                 * Err could be -1 in case a duplicate metaconn is inserted
+                *
+                * FIXME: what if the same client issues more than one
+                * asynchronous operations?
                 */
-               if ( err == 0 ) {
-                       Debug( LDAP_DEBUG_TRACE,
-                               "%s meta_back_getconn: candidates=%d conn=%ld inserted\n",
-                               op->o_log_prefix, ncandidates, mc->mc_conn->c_connid );
-
-               } else {
+               if ( err != 0 ) {
                        Debug( LDAP_DEBUG_ANY,
                                "%s meta_back_getconn: candidates=%d conn=%ld insert failed\n",
                                op->o_log_prefix, ncandidates, mc->mc_conn->c_connid );
                
                        rs->sr_err = LDAP_OTHER;
                        rs->sr_text = "Internal server error";
-                       meta_back_conn_free( mc );
+                       meta_back_freeconn( op, mc );
                        if ( sendok & LDAP_BACK_SENDERR ) {
                                send_ldap_result( op, rs );
                                rs->sr_text = NULL;
@@ -907,6 +1042,10 @@ done:;
                        return NULL;
                }
 
+               Debug( LDAP_DEBUG_TRACE,
+                       "%s meta_back_getconn: candidates=%d conn=%ld inserted\n",
+                       op->o_log_prefix, ncandidates, mc->mc_conn->c_connid );
+
        } else {
                Debug( LDAP_DEBUG_TRACE,
                        "%s meta_back_getconn: candidates=%d conn=%ld fetched\n",
@@ -916,3 +1055,27 @@ done:;
        return mc;
 }
 
+void
+meta_back_release_conn(
+               Operation               *op,
+       metaconn_t              *mc )
+{
+       metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
+
+       assert( mc != NULL );
+
+retry_lock:;
+       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
+       case LDAP_PVT_THREAD_EBUSY:
+       default:
+               ldap_pvt_thread_yield();
+               goto retry_lock;
+
+       case 0:
+               break;
+       }
+
+       assert( mc->mc_refcnt > 0 );
+       mc->mc_refcnt--;
+       ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
+}
index 94d9a330d888e81f912f078160229176c2195094..d247de359a4cc288a7845acbd99b1b0578bc86b8 100644 (file)
@@ -35,7 +35,7 @@ int
 meta_back_delete( Operation *op, SlapReply *rs )
 {
        metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
-       metaconn_t      *mc;
+       metaconn_t      *mc = NULL;
        int             candidate = -1;
        struct berval   mdn = BER_BVNULL;
        dncookie        dc;
@@ -58,7 +58,7 @@ meta_back_delete( Operation *op, SlapReply *rs )
 
        if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
                send_ldap_result( op, rs );
-               return -1;
+               goto done;
        }
 
 retry:;
@@ -76,6 +76,11 @@ retry:;
                BER_BVZERO( &mdn );
        }
        
-       return meta_back_op_result( mc, op, rs, candidate );
+       rs->sr_err = meta_back_op_result( mc, op, rs, candidate );
+
+done:;
+       meta_back_release_conn( op, mc );
+
+       return rs->sr_err;
 }
 
index 336f00171303d65ea08997f9c0f99f638e1cb66b..3b50226603d2826e39df0dd19bd13fc7f8571ddf 100644 (file)
@@ -108,7 +108,8 @@ meta_back_db_open(
        int             i, rc;
 
        for ( i = 0; i < mi->mi_ntargets; i++ ) {
-               if ( mi->mi_targets[ i ].mt_flags & LDAP_BACK_F_SUPPORT_T_F_DISCOVER ) {
+               if ( mi->mi_targets[ i ].mt_flags & LDAP_BACK_F_SUPPORT_T_F_DISCOVER )
+               {
                        mi->mi_targets[ i ].mt_flags &= ~LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
                        rc = slap_discover_feature( mi->mi_targets[ i ].mt_uri,
                                        mi->mi_targets[ i ].mt_version,
index 62533e339fce054531d0467a6c0a4becffd38ced..87ca4b903175cdae6c7750b8098848d40bea291b 100644 (file)
@@ -483,43 +483,40 @@ ldap_back_int_filter_map_rewrite(
                ber_memfree( vtmp.bv_val );
                break;
 
-       case SLAPD_FILTER_COMPUTED:
+       case SLAPD_FILTER_COMPUTED: {
+               struct berval   bv;
+
                switch ( f->f_result ) {
                case LDAP_COMPARE_FALSE:
                        if ( dc->target->mt_flags & LDAP_BACK_F_SUPPORT_T_F ) {
-                               ber_str2bv( "(|)", STRLENOF( "(|)" ), 1, fstr );
-
-                       } else {
-#if 0
-                               ber_str2bv( "(?=false)", STRLENOF( "(?=false)" ), 1, fstr );
-#endif
-                               /* better than nothing... */
-                               ber_str2bv( "(!(objectClass=*))", STRLENOF( "(!(objectClass=*))" ), 1, fstr );
+                               BER_BVSTR( &bv, "(|)" );
+                               break;
                        }
+                       /* fallthru */
+
+               /* FIXME: treat UNDEFINED as FALSE */
+               case SLAPD_COMPARE_UNDEFINED:
+                       /* better than nothing... */
+                       BER_BVSTR( &bv, "(!(objectClass=*))" );
                        break;
 
                case LDAP_COMPARE_TRUE:
                        if ( dc->target->mt_flags & LDAP_BACK_F_SUPPORT_T_F ) {
-                               ber_str2bv( "(&)", STRLENOF( "(&)" ), 1, fstr );
-
-                       } else {
-#if 0
-                               ber_str2bv( "(?=true)", STRLENOF( "(?=true)" ), 1, fstr );
-#endif
-                               /* better than nothing... */
-                               ber_str2bv( "(objectClass=*)", STRLENOF( "(objectClass=*)" ), 1, fstr );
+                               BER_BVSTR( &bv, "(&)" );
+                               break;
                        }
-                       break;
 
-               case SLAPD_COMPARE_UNDEFINED:
-                       ber_str2bv( "(?=undefined)", STRLENOF( "(?=undefined)" ), 1, fstr );
+                       /* better than nothing... */
+                       BER_BVSTR( &bv, "(objectClass=*)" );
                        break;
 
                default:
-                       ber_str2bv( "(?=error)", STRLENOF( "(?=error)" ), 1, fstr );
+                       BER_BVSTR( &bv, "(?=error)" );
                        break;
                }
-               break;
+
+               ber_dupbv( fstr, &bv );
+               } break;
 
        default:
                ber_str2bv( "(?=unknown)", STRLENOF( "(?=unknown)" ), 1, fstr );
index 62a041a17f5f6904cadd82482c8782d0a68a5fc0..2d51289cb11aa8ba2da2138c0c22e77946eb08b5 100644 (file)
@@ -195,11 +195,15 @@ cleanup:;
        free( modv );
 
        if ( rc != -1 ) {
-               return meta_back_op_result( mc, op, rs, candidate );
+               rc = meta_back_op_result( mc, op, rs, candidate );
+
+       } else {
+               send_ldap_result( op, rs );
+               rc = 0;
        }
-       
-       send_ldap_result( op, rs );
 
-       return rs->sr_err;
+       meta_back_release_conn( op, mc );
+
+       return rc;
 }
 
index b5396f9b36a0697bb81d3f1c98463effb0f1d620..a63e99e48c731ad0d9ae763ce57fc5f4c3c7a263 100644 (file)
@@ -131,6 +131,8 @@ cleanup:;
 
        send_ldap_result( op, rs );
 
+       meta_back_release_conn( op, mc );
+
        return rs->sr_err;
 }
 
index fe1e403a21cec4e0f88f6708afbc4f9926f567b8..30e0d9ba22d5f972efcacab5495677b8e7c3fe15 100644 (file)
@@ -267,6 +267,7 @@ meta_back_search( Operation *op, SlapReply *rs )
                if ( candidates[ i ].sr_tag != META_CANDIDATE ) {
                        continue;
                }
+
                candidates[ i ].sr_err = LDAP_SUCCESS;
                candidates[ i ].sr_matched = NULL;
                candidates[ i ].sr_text = NULL;
@@ -359,8 +360,6 @@ meta_back_search( Operation *op, SlapReply *rs )
                                        0, &tv, &res );
 
                        if ( rc == 0 ) {
-                               /* timeout exceeded */
-
                                /* FIXME: res should not need to be freed */
                                assert( res == NULL );
 
@@ -514,7 +513,7 @@ really_bad:;
                                                        (char **)&candidates[ i ].sr_matched,
                                                        NULL /* (char **)&candidates[ i ].sr_text */ ,
                                                        &references,
-                                                       &candidates[ i ].sr_ctrls, 1 ) )
+                                                       &candidates[ i ].sr_ctrls, 1 ) != LDAP_SUCCESS )
                                {
                                        res = NULL;
                                        ldap_get_option( msc->msc_ld,
@@ -523,6 +522,7 @@ really_bad:;
                                        sres = slap_map_api2result( rs );
                                        goto really_bad;
                                }
+
                                rs->sr_err = candidates[ i ].sr_err;
                                sres = slap_map_api2result( rs );
                                res = NULL;
@@ -596,6 +596,15 @@ really_bad:;
 
                                rs->sr_err = candidates[ i ].sr_err;
                                sres = slap_map_api2result( rs );
+
+                               snprintf( buf, sizeof( buf ),
+                                       "%s meta_back_search[%d] "
+                                       "match=\"%s\" err=%d\n",
+                                       op->o_log_prefix, i,
+                                       candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
+                                       candidates[ i ].sr_err );
+                               Debug( LDAP_DEBUG_ANY, "%s", buf, 0, 0 );
+
                                switch ( sres ) {
                                case LDAP_NO_SUCH_OBJECT:
                                        /* is_ok is touched any time a valid
@@ -613,15 +622,17 @@ really_bad:;
                                case LDAP_REFERRAL:
                                        is_ok++;
                                        break;
-                               }
 
-                               snprintf( buf, sizeof( buf ),
-                                       "%s meta_back_search[%d] "
-                                       "match=\"%s\" err=%d\n",
-                                       op->o_log_prefix, i,
-                                       candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
-                                       candidates[ i ].sr_err );
-                               Debug( LDAP_DEBUG_ANY, "%s", buf, 0, 0 );
+                               default:
+                                       if ( META_BACK_ONERR_STOP( mi ) ) {
+                                               savepriv = op->o_private;
+                                               op->o_private = (void *)i;
+                                               send_ldap_result( op, rs );
+                                               op->o_private = savepriv;
+                                               goto finish;
+                                       }
+                                       break;
+                               }
 
                                last = i;
                                rc = 0;
@@ -773,6 +784,8 @@ finish:;
                }
        }
 
+       meta_back_release_conn( op, mc );
+
        return rc;
 }
 
index 97f26bc7db9a7c030bb61e07bce609f26887568d..1fd72e7271e6e8021099cd85743a8a804154ccbe 100644 (file)
@@ -24,9 +24,9 @@
 
 #include <stdio.h>
 
+#include <ac/errno.h>
 #include <ac/socket.h>
 #include <ac/string.h>
-#include <ac/errno.h>
 
 #include "slap.h"
 #include "../back-ldap/back-ldap.h"
@@ -38,7 +38,7 @@ meta_back_conn_destroy(
        Connection      *conn )
 {
        metainfo_t      *mi = ( metainfo_t * )be->be_private;
-       metaconn_t *mc,
+       metaconn_t      *mc,
                        mc_curr = { 0 };
 
        Debug( LDAP_DEBUG_TRACE,
@@ -47,7 +47,17 @@ meta_back_conn_destroy(
        
        mc_curr.mc_conn = conn;
        
-       ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
+retry_lock:;
+       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
+       case LDAP_PVT_THREAD_EBUSY:
+       default:
+               ldap_pvt_thread_yield();
+               goto retry_lock;
+
+       case 0:
+               break;
+       }
+
        mc = avl_delete( &mi->mi_conntree, ( caddr_t )&mc_curr,
                        meta_back_conn_cmp );
        ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
@@ -59,16 +69,17 @@ meta_back_conn_destroy(
                        "=>meta_back_conn_destroy: destroying conn %ld\n",
                        mc->mc_conn->c_connid, 0, 0 );
                
+               assert( mc->mc_refcnt == 0 );
+
                /*
                 * Cleanup rewrite session
                 */
                for ( i = 0; i < mi->mi_ntargets; ++i ) {
-                       if ( mc->mc_conns[ i ].msc_ld == NULL ) {
-                               continue;
-                       }
-
                        rewrite_session_delete( mi->mi_targets[ i ].mt_rwmap.rwm_rw, conn );
-                       meta_clear_one_candidate( &mc->mc_conns[ i ] );
+
+                       if ( mc->mc_conns[ i ].msc_ld != NULL ) {
+                               meta_clear_one_candidate( &mc->mc_conns[ i ] );
+                       }
                }
                meta_back_conn_free( mc );
        }
index e31d3b85eb470b856aa982199c2de1f741bdb367..90906ce294639b56cfe0531891f05cfa36d6e8cd 100644 (file)
@@ -39,9 +39,9 @@ sql_back_initialize(
 #if 0 /* needs improvements */
                LDAP_CONTROL_NOOP,
 #endif
-#ifdef LDAP_CONTROL_X_TREE_DELETE
-               LDAP_CONTROL_X_TREE_DELETE,
-#endif /* LDAP_CONTROL_X_TREE_DELETE */
+#ifdef SLAP_CONTROL_X_TREE_DELETE
+               SLAP_CONTROL_X_TREE_DELETE,
+#endif /* SLAP_CONTROL_X_TREE_DELETE */
                NULL
        };
 
index 7fc267a259970d99fc174b928079d2702189aa37..9e352079cd3ac438563c1d677a713e3b975a551c 100644 (file)
@@ -778,7 +778,7 @@ backend_connection_init(
 
        LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
                if ( be->be_connection_init ) {
-                       be->be_connection_init( be, conn);
+                       be->be_connection_init( be, conn );
                }
        }
 
index 047af4497b5d5ade70ad2360068873c0adb91ccb..90c395a40f5fab6241c95a5b96b0ec98f3cc6327 100644 (file)
@@ -230,45 +230,6 @@ over_back_response ( Operation *op, SlapReply *rs )
        return rc;
 }
 
-enum op_which {
-       op_bind = 0,
-       op_unbind,
-       op_search,
-       op_compare,
-       op_modify,
-       op_modrdn,
-       op_add,
-       op_delete,
-       op_abandon,
-       op_cancel,
-       op_extended,
-       op_aux_operational,
-       op_aux_chk_referrals,
-       op_aux_chk_controls,
-       op_last
-};
-
-/*
- * default return code in case of missing backend function
- * and overlay stack returning SLAP_CB_CONTINUE
- */
-static int op_rc[] = {
-       LDAP_UNWILLING_TO_PERFORM,      /* bind */
-       LDAP_UNWILLING_TO_PERFORM,      /* unbind */
-       LDAP_UNWILLING_TO_PERFORM,      /* search */
-       SLAP_CB_CONTINUE,               /* compare; pass to frontend */
-       LDAP_UNWILLING_TO_PERFORM,      /* modify */
-       LDAP_UNWILLING_TO_PERFORM,      /* modrdn */
-       LDAP_UNWILLING_TO_PERFORM,      /* add */
-       LDAP_UNWILLING_TO_PERFORM,      /* delete */
-       LDAP_UNWILLING_TO_PERFORM,      /* abandon */
-       LDAP_UNWILLING_TO_PERFORM,      /* cancel */
-       LDAP_UNWILLING_TO_PERFORM,      /* extended */
-       LDAP_SUCCESS,                   /* aux_operational */
-       LDAP_SUCCESS,                   /* aux_chk_referrals */
-       SLAP_CB_CONTINUE                /* aux_chk_controls; pass to frontend */
-};
-
 #ifdef SLAP_OVERLAY_ACCESS
 static int
 over_access_allowed(
@@ -340,6 +301,45 @@ over_access_allowed(
 }
 #endif /* SLAP_OVERLAY_ACCESS */
 
+enum op_which {
+       op_bind = 0,
+       op_unbind,
+       op_search,
+       op_compare,
+       op_modify,
+       op_modrdn,
+       op_add,
+       op_delete,
+       op_abandon,
+       op_cancel,
+       op_extended,
+       op_aux_operational,
+       op_aux_chk_referrals,
+       op_aux_chk_controls,
+       op_last
+};
+
+/*
+ * default return code in case of missing backend function
+ * and overlay stack returning SLAP_CB_CONTINUE
+ */
+static int op_rc[] = {
+       LDAP_UNWILLING_TO_PERFORM,      /* bind */
+       LDAP_UNWILLING_TO_PERFORM,      /* unbind */
+       LDAP_UNWILLING_TO_PERFORM,      /* search */
+       SLAP_CB_CONTINUE,               /* compare; pass to frontend */
+       LDAP_UNWILLING_TO_PERFORM,      /* modify */
+       LDAP_UNWILLING_TO_PERFORM,      /* modrdn */
+       LDAP_UNWILLING_TO_PERFORM,      /* add */
+       LDAP_UNWILLING_TO_PERFORM,      /* delete */
+       LDAP_UNWILLING_TO_PERFORM,      /* abandon */
+       LDAP_UNWILLING_TO_PERFORM,      /* cancel */
+       LDAP_UNWILLING_TO_PERFORM,      /* extended */
+       LDAP_SUCCESS,                   /* aux_operational */
+       LDAP_SUCCESS,                   /* aux_chk_referrals */
+       SLAP_CB_CONTINUE                /* aux_chk_controls; pass to frontend */
+};
+
 static int
 over_op_func(
        Operation *op,
@@ -491,16 +491,23 @@ over_aux_chk_controls( Operation *op, SlapReply *rs )
        return over_op_func( op, rs, op_aux_chk_controls );
 }
 
+enum conn_which {
+       conn_init = 0,
+       conn_destroy
+};
+
 static int
-over_connection_destroy(
+over_connection_func(
        BackendDB       *bd,
-       Connection      *conn
+       Connection      *conn,
+       enum conn_which which
 )
 {
-       slap_overinfo *oi;
-       slap_overinst *on;
-       BackendDB db;
-       int rc = SLAP_CB_CONTINUE;
+       slap_overinfo           *oi;
+       slap_overinst           *on;
+       BackendDB               db;
+       int                     rc = SLAP_CB_CONTINUE;
+       BI_connection_init      **func;
 
        /* FIXME: used to happen for instance during abandon
         * when global overlays are used... */
@@ -509,23 +516,25 @@ over_connection_destroy(
        oi = bd->bd_info->bi_private;
        on = oi->oi_list;
 
-       if ( !SLAP_ISOVERLAY( bd )) {
+       if ( !SLAP_ISOVERLAY( bd ) ) {
                db = *bd;
                db.be_flags |= SLAP_DBFLAG_OVERLAY;
                bd = &db;
        }
 
-       for (; on; on=on->on_next ) {
-               if ( on->on_bi.bi_connection_destroy ) {
+       for ( ; on; on = on->on_next ) {
+               func = &on->on_bi.bi_connection_init;
+               if ( func[ which ] ) {
                        bd->bd_info = (BackendInfo *)on;
-                       rc = on->on_bi.bi_connection_destroy( bd, conn );
+                       rc = func[ which ]( bd, conn );
                        if ( rc != SLAP_CB_CONTINUE ) break;
                }
        }
 
-       if ( oi->oi_orig->bi_connection_destroy && rc == SLAP_CB_CONTINUE ) {
+       func = &oi->oi_orig->bi_connection_init;
+       if ( func[ which ] && rc == SLAP_CB_CONTINUE ) {
                bd->bd_info = oi->oi_orig;
-               rc = oi->oi_orig->bi_connection_destroy( bd, conn );
+               rc = func[ which ]( bd, conn );
        }
        /* should not fall thru this far without anything happening... */
        if ( rc == SLAP_CB_CONTINUE ) {
@@ -535,6 +544,24 @@ over_connection_destroy(
        return rc;
 }
 
+static int
+over_connection_init(
+       BackendDB       *bd,
+       Connection      *conn
+)
+{
+       return over_connection_func( bd, conn, conn_init );
+}
+
+static int
+over_connection_destroy(
+       BackendDB       *bd,
+       Connection      *conn
+)
+{
+       return over_connection_func( bd, conn, conn_destroy );
+}
+
 int
 overlay_register(
        slap_overinst *on
@@ -750,6 +777,7 @@ overlay_config( BackendDB *be, const char *ov )
                bi->bi_access_allowed = over_access_allowed;
 #endif /* SLAP_OVERLAY_ACCESS */
                
+               bi->bi_connection_init = over_connection_init;
                bi->bi_connection_destroy = over_connection_destroy;
 
                be->bd_info = bi;
index e702927bc8d7583d0ba25621b26341c65570149a..91c865976520a23a4c89d48d80cd40ba0fe6752f 100644 (file)
@@ -159,6 +159,8 @@ enum {
        CFG_SASLSECP,
        CFG_SSTR_IF_MAX,
        CFG_SSTR_IF_MIN,
+
+       CFG_LAST
 };
 
 typedef struct {
@@ -223,6 +225,10 @@ static ConfigTable config_back_cf_table[] = {
                        "DESC 'File for slapd command line options' "
                        "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+       { "attributeoptions", NULL, 0, 0, 0, ARG_MAGIC|CFG_ATOPT,
+               &config_generic, "( OLcfgGlAt:5 NAME 'olcAttributeOptions' "
+                       "EQUALITY caseIgnoreMatch "
+                       "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "attribute",  "attribute", 2, 0, 9,
                ARG_PAREN|ARG_MAGIC|CFG_ATTR|ARG_NO_DELETE|ARG_NO_INSERT,
                &config_generic, "( OLcfgGlAt:4 NAME 'olcAttributeTypes' "
@@ -230,10 +236,6 @@ static ConfigTable config_back_cf_table[] = {
                        "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
                                NULL, NULL },
-       { "attributeoptions", NULL, 0, 0, 0, ARG_MAGIC|CFG_ATOPT,
-               &config_generic, "( OLcfgGlAt:5 NAME 'olcAttributeOptions' "
-                       "EQUALITY caseIgnoreMatch "
-                       "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "authid-rewrite", NULL, 2, 0, STRLENOF( "authid-rewrite" ),
 #ifdef SLAP_AUTH_REWRITE
                ARG_MAGIC|CFG_REWRITE|ARG_NO_INSERT, &config_generic,
@@ -270,7 +272,7 @@ static ConfigTable config_back_cf_table[] = {
                &config_generic, "( OLcfgGlAt:13 NAME 'olcDatabase' "
                        "DESC 'The backend type for a database instance' "
                        "SUP olcBackend SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL },
-       { "defaultSearchBase", "dn", 2, 2, 0, ARG_PRE_BI|ARG_PRE_DB|ARG_DN|ARG_MAGIC,
+       { "defaultSearchBase", "dn", 2, 2, 0, ARG_PRE_BI|ARG_PRE_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
                &config_search_base, "( OLcfgGlAt:14 NAME 'olcDefaultSearchBase' "
                        "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
        { "disallows", "features", 2, 0, 8, ARG_PRE_DB|ARG_MAGIC,
@@ -306,7 +308,7 @@ static ConfigTable config_back_cf_table[] = {
        { "index_substr_any_len", "len", 2, 2, 0, ARG_INT|ARG_NONZERO,
                &index_substr_any_len, "( OLcfgGlAt:22 NAME 'olcIndexSubstrAnyLen' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
-       { "index_substr_step", "step", 2, 2, 0, ARG_INT|ARG_NONZERO,
+       { "index_substr_any_step", "step", 2, 2, 0, ARG_INT|ARG_NONZERO,
                &index_substr_any_step, "( OLcfgGlAt:23 NAME 'olcIndexSubstrAnyStep' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
        { "lastmod", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_LASTMOD,
@@ -415,7 +417,7 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:49 NAME 'olcReverseLookup' "
                        "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
-       { "rootdn", "dn", 2, 2, 0, ARG_DB|ARG_DN|ARG_MAGIC,
+       { "rootdn", "dn", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
                &config_rootdn, "( OLcfgDbAt:0.8 NAME 'olcRootDN' "
                        "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
        { "rootDSE", "file", 2, 2, 0, ARG_MAGIC|CFG_ROOTDSE,
@@ -454,7 +456,7 @@ static ConfigTable config_back_cf_table[] = {
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
        { "saslRegexp", NULL, 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP,
                &config_generic, NULL, NULL, NULL },
-       { "schemadn", "dn", 2, 2, 0, ARG_MAY_DB|ARG_DN|ARG_MAGIC,
+       { "schemadn", "dn", 2, 2, 0, ARG_MAY_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
                &config_schema_dn, "( OLcfgGlAt:58 NAME 'olcSchemaDN' "
                        "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
        { "security", "factors", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
@@ -477,7 +479,7 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:63 NAME 'olcSrvtab' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-       { "suffix",     "suffix", 2, 2, 0, ARG_DB|ARG_DN|ARG_MAGIC,
+       { "suffix",     "suffix", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
                &config_suffix, "( OLcfgDbAt:0.10 NAME 'olcSuffix' "
                        "SYNTAX OMsDN )", NULL, NULL },
        { "syncrepl", NULL, 0, 0, 0, ARG_DB|ARG_MAGIC,
@@ -555,7 +557,7 @@ static ConfigTable config_back_cf_table[] = {
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
        { "ucdata-path", "path", 2, 2, 0, ARG_IGNORED,
                NULL, NULL, NULL, NULL },
-       { "updatedn", "dn", 2, 2, 0, ARG_DB|ARG_MAGIC,
+       { "updatedn", "dn", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
                &config_updatedn, "( OLcfgDbAt:0.12 NAME 'olcUpdateDN' "
                        "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
        { "updateref", "url", 2, 2, 0, ARG_DB|ARG_MAGIC,
@@ -692,7 +694,8 @@ config_generic(ConfigArgs *c) {
                        if ( !c->rvalue_vals ) rc = 1;
                        break;
                case CFG_RO:
-                       c->value_int = (c->be->be_restrictops & SLAP_RESTRICT_OP_WRITES) != 0;
+                       c->value_int = (c->be->be_restrictops & SLAP_RESTRICT_OP_WRITES) ==
+                               SLAP_RESTRICT_OP_WRITES;
                        break;
                case CFG_AZPOLICY:
                        c->value_string = ch_strdup( slap_sasl_getpolicy());
@@ -2787,8 +2790,9 @@ check_vals( ConfigTable *ct, ConfigArgs *ca, void *ptr, int isAttr )
                        if ( idx ) ca->line = idx+1;
                }
                rc = config_parse_vals( ct, ca, i );
-               if ( rc )
+               if ( rc ) {
                        break;
+               }
        }
        return rc;
 }
@@ -3169,10 +3173,6 @@ ok:
                        Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
                                ca->log, ca->msg, ca->argv[1] );
                        rc = LDAP_OTHER;
-                       if ( colst[0]->co_type == Cft_Database )
-                               backend_destroy_one( ca->be );
-                       else
-                               overlay_destroy_one( ca->be, (slap_overinst *)ca->bi );
                        goto leave;
                }
        }
@@ -3198,6 +3198,14 @@ ok:
        }
 
 leave:
+       if ( rc ) {
+               if ( (colst[0]->co_type == Cft_Database) && ca->be ) {
+                       backend_destroy_one( ca->be );
+               } else if ( (colst[0]->co_type == Cft_Overlay) && ca->bi ) {
+                       overlay_destroy_one( ca->be, (slap_overinst *)ca->bi );
+               }
+       }
+
        ch_free( ca->argv );
        if ( colst ) ch_free( colst );
        return rc;
@@ -4189,6 +4197,9 @@ config_back_initialize( BackendInfo *bi )
        bi->bi_tool_entry_get = config_tool_entry_get;
        bi->bi_tool_entry_put = config_tool_entry_put;
 
+       /* Make sure we don't exceed the bits reserved for userland */
+       assert( ( ( CFG_LAST - 1 ) & ARGS_USERLAND ) == ( CFG_LAST - 1 ) );
+
        argv[3] = NULL;
        for (i=0; OidMacros[i].name; i++ ) {
                argv[1] = OidMacros[i].name;
index c39caea9f64e37be8a26d0ead16d2685e5fa49bd..6dac6e2a6b2a3fc7a4c4509fd6e8237dff7a9a97 100644 (file)
@@ -449,7 +449,7 @@ fe_op_bind( Operation *op, SlapReply *rs )
 
                send_ldap_result( op, rs );
                Debug( LDAP_DEBUG_TRACE,
-                       "do_bind: v%d unknown authentication method (%ld)\n",
+                       "do_bind: v%d unknown authentication method (%d)\n",
                        op->o_protocol, op->orb_method, 0 );
                goto cleanup;
        }
index bb66c4cee7bc23a1f230db690e5f664bf5a3c3bd..7633af36de03b79ec25b79ce2b5b1ba4741d4d40 100644 (file)
@@ -447,7 +447,8 @@ get_componentId( Operation *op, ComponentAssertionValue* cav,
 
        type = peek_componentId_type( cav );
 
-       Debug( LDAP_DEBUG_FILTER, "get_compId [%d]\n", type, 0, 0 );
+       Debug( LDAP_DEBUG_FILTER, "get_compId [%lu]\n",
+               (unsigned long) type, 0, 0 );
        len = 0;
        _cid.ci_type = type;
        _cid.ci_next = NULL;
index b446dcc4ca7ae7705e45f9979ecb8879ecca5b9d..acf465c2fd834c247386730136b3f29bee335bd6 100644 (file)
@@ -92,7 +92,7 @@ new_config_args( BackendDB *be, const char *fname, int lineno, int argc, char **
        c->argc   = argc;
        c->argv   = argv; 
        c->lineno = lineno;
-       snprintf( c->log, sizeof( c->log ), "%s: line %lu", fname, lineno );
+       snprintf( c->log, sizeof( c->log ), "%s: line %d", fname, lineno );
        return(c);
 }
 
@@ -473,17 +473,34 @@ init_config_ocs( ConfigOCs *ocs ) {
 int
 config_parse_vals(ConfigTable *ct, ConfigArgs *c, int valx)
 {
-       int rc = 0;
+       int     rc = 0;
+       char    *saveline = NULL;
 
        snprintf( c->log, sizeof( c->log ), "%s: value #%d",
                ct->ad->ad_cname.bv_val, valx );
        c->argc = 1;
        c->argv[0] = ct->ad->ad_cname.bv_val;
+
+       if ( ( ct->arg_type & ARG_QUOTE ) && c->line[ 0 ] != '"' ) {
+               ber_len_t       len;
+
+               saveline = c->line;
+               len = strlen( c->line );
+               c->line = ch_malloc( len + STRLENOF( "\"\"" ) + 1 );
+               sprintf( c->line, "\"%s\"", saveline );
+       }
+
        if ( fp_parse_line( c ) ) {
                rc = 1;
        } else {
                rc = config_check_vals( ct, c, 1 );
        }
+
+       if ( saveline ) {
+               ch_free( c->line );
+               c->line = saveline;
+       }
+
        if ( rc )
                rc = LDAP_CONSTRAINT_VIOLATION;
 
@@ -494,12 +511,24 @@ config_parse_vals(ConfigTable *ct, ConfigArgs *c, int valx)
 int
 config_parse_add(ConfigTable *ct, ConfigArgs *c)
 {
-       int rc = 0;
+       int     rc = 0;
+       char    *saveline = NULL;
 
        snprintf( c->log, sizeof( c->log ), "%s: value #%d",
                ct->ad->ad_cname.bv_val, c->valx );
        c->argc = 1;
        c->argv[0] = ct->ad->ad_cname.bv_val;
+
+       if ( ( ct->arg_type & ARG_QUOTE ) && c->line[ 0 ] != '"' ) {
+               ber_len_t       len;
+
+               saveline = c->line;
+               len = strlen( c->line );
+                       
+               c->line = ch_malloc( len + STRLENOF( "\"\"" ) + 1 );
+               sprintf( c->line, "\"%s\"", saveline );
+       }
+
        if ( fp_parse_line( c ) ) {
                rc = 1;
        } else {
@@ -507,6 +536,11 @@ config_parse_add(ConfigTable *ct, ConfigArgs *c)
                rc = config_add_vals( ct, c );
        }
 
+       if ( saveline ) {
+               ch_free( c->line );
+               c->line = saveline;
+       }
+
        ch_free( c->tline );
        return rc;
 }
@@ -1157,7 +1191,7 @@ int config_generic_wrapper( Backend *be, const char *fname, int lineno,
        c.argc = argc;
        c.argv = argv;
        c.valx = -1;
-       sprintf( c.log, "%s: line %lu", fname, lineno );
+       sprintf( c.log, "%s: line %d", fname, lineno );
 
        rc = SLAP_CONF_UNKNOWN;
        ct = config_find_keyword( be->be_cf_ocs->co_table, &c );
index bee94817e22d63637206403a34546d2f12013c66..5ddd7552c0962f9f72f718758179a37d63d7175c 100644 (file)
@@ -62,6 +62,7 @@ typedef enum {
 #define        ARG_NO_INSERT   0x04000000      /* no arbitrary inserting */
 #define        ARG_NO_DELETE   0x08000000      /* no runtime deletes */
 #define ARG_UNIQUE     0x10000000
+#define        ARG_QUOTE       0x20000000      /* wrap with quotes before parsing */
 #define ARG_OFFSET     0x40000000
 #define ARG_MAGIC      0x80000000
 
index 2f9ab790610e39ae41a45572783d1e1dfb773728..036f7ae0e17f2eeaf8f0371bc9a5cedfeb61158e 100644 (file)
@@ -1474,16 +1474,32 @@ connection_input(
         * already pending ops, let them go first.  Abandon operations
         * get exceptions to some, but not all, cases.
         */
-       if (tag != LDAP_REQ_ABANDON && conn->c_conn_state == SLAP_C_CLOSING) {
-               defer = "closing";
-       } else if (tag != LDAP_REQ_ABANDON && conn->c_writewaiter) {
-               defer = "awaiting write";
-       } else if (conn->c_n_ops_executing >= connection_pool_max/2) {
-               defer = "too many executing";
-       } else if (conn->c_conn_state == SLAP_C_BINDING) {
-               defer = "binding";
-       } else if (tag != LDAP_REQ_ABANDON && conn->c_n_ops_pending) {
-               defer = "pending operations";
+       switch( tag ){
+       default:
+               /* Abandon and Unbind are exempt from these checks */
+               if (conn->c_conn_state == SLAP_C_CLOSING) {
+                       defer = "closing";
+                       break;
+               } else if (conn->c_writewaiter) {
+                       defer = "awaiting write";
+                       break;
+               } else if (conn->c_n_ops_pending) {
+                       defer = "pending operations";
+                       break;
+               }
+               /* FALLTHRU */
+       case LDAP_REQ_ABANDON:
+               /* Unbind is exempt from these checks */
+               if (conn->c_n_ops_executing >= connection_pool_max/2) {
+                       defer = "too many executing";
+                       break;
+               } else if (conn->c_conn_state == SLAP_C_BINDING) {
+                       defer = "binding";
+                       break;
+               }
+               /* FALLTHRU */
+       case LDAP_REQ_UNBIND:
+               break;
        }
 
        if( defer ) {
index 5699329c6efa64eb0c135f62086310cff94d8831..a3c686312c76526bdb717c6bfdfa09e867a68154 100644 (file)
@@ -41,7 +41,9 @@ static SLAP_CTRL_PARSE_FN parseSortedResults;
 static SLAP_CTRL_PARSE_FN parseValuesReturnFilter;
 static SLAP_CTRL_PARSE_FN parsePermissiveModify;
 static SLAP_CTRL_PARSE_FN parseDomainScope;
+#ifdef SLAP_CONTROL_X_TREE_DELETE
 static SLAP_CTRL_PARSE_FN parseTreeDelete;
+#endif
 static SLAP_CTRL_PARSE_FN parseSearchOptions;
 static SLAP_CTRL_PARSE_FN parseSubentries;
 
@@ -1325,7 +1327,7 @@ static int parseDomainScope (
 }
 #endif
 
-#ifdef LDAP_CONTROL_X_TREE_DELETE
+#ifdef SLAP_CONTROL_X_TREE_DELETE
 static int parseTreeDelete (
        Operation *op,
        SlapReply *rs,
index 2797e85ecfc74dc530c1be9179c03012676d99d0..6abea22fc210c6779d463658ea803fb069f11aef 100644 (file)
@@ -1372,12 +1372,15 @@ slapd_handle_listener(
 
                        if( getpeereid( s, &uid, &gid ) == 0 ) {
                                authid.bv_val = ch_malloc(
-                                       sizeof("uidnumber=4294967295+gidnumber=4294967295,"
-                                       "cn=peercred,cn=external,cn=auth"));
+                                       STRLENOF( "gidNumber=4294967295+uidNumber=4294967295,"
+                                       "cn=peercred,cn=external,cn=auth" ) + 1 );
                                authid.bv_len = sprintf( authid.bv_val,
-                                       "uidnumber=%d+gidnumber=%d,"
+                                       "gidNumber=%d+uidNumber=%d,"
                                        "cn=peercred,cn=external,cn=auth",
-                                       (int) uid, (int) gid);
+                                       (int) gid, (int) uid );
+                               assert( authid.bv_len <=
+                                       STRLENOF( "gidNumber=4294967295+uidNumber=4294967295,"
+                                       "cn=peercred,cn=external,cn=auth" ) );
                        }
                }
                dnsname = "local";
@@ -2010,9 +2013,6 @@ slapd_daemon_task(
                close_listeners ( 0 );
        }
 
-       free ( slap_listeners );
-       slap_listeners = NULL;
-
        if( !slapd_gentle_shutdown ) {
                slapd_abrupt_shutdown = 1;
                connections_shutdown();
@@ -2023,6 +2023,9 @@ slapd_daemon_task(
            ldap_pvt_thread_pool_backload(&connection_pool), 0, 0 );
        ldap_pvt_thread_pool_destroy(&connection_pool, 1);
 
+       free ( slap_listeners );
+       slap_listeners = NULL;
+
        return NULL;
 }
 
index 0bfc702e6a03d3469633317f62c67e7e0deea4dc..0d7527c0eb5f746cd4e7d2be83531049c4d9d429 100644 (file)
@@ -173,7 +173,7 @@ get_filter(
                if( err != LDAP_SUCCESS ) {
                        /* unrecognized attribute description or other error */
                        Debug( LDAP_DEBUG_ANY, 
-                               "get_filter: conn %d unknown attribute "
+                               "get_filter: conn %lu unknown attribute "
                                "type=%s (%d)\n",
                                op->o_connid, type.bv_val, err );
 
@@ -349,8 +349,8 @@ get_ssa(
 
        if( rc != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_ANY, 
-                       "get_ssa: conn %d unknown attribute type=%s (%d)\n",
-                       op->o_connid, desc.bv_val, rc );
+                       "get_ssa: conn %lu unknown attribute type=%s (%ld)\n",
+                       op->o_connid, desc.bv_val, (long) rc );
 
                /* skip over the rest of this filter */
                for ( tag = ber_first_element( ber, &len, &last );
@@ -382,24 +382,39 @@ get_ssa(
 
                switch ( tag ) {
                case LDAP_SUBSTRING_INITIAL:
+                       if ( ssa.sa_initial.bv_val != NULL
+                               || ssa.sa_any != NULL 
+                               || ssa.sa_final.bv_val != NULL )
+                       {
+                               rc = LDAP_PROTOCOL_ERROR;
+                               goto return_error;
+                       }
                        usage = SLAP_MR_SUBSTR_INITIAL;
                        break;
 
                case LDAP_SUBSTRING_ANY:
+                       if ( ssa.sa_final.bv_val != NULL ) {
+                               rc = LDAP_PROTOCOL_ERROR;
+                               goto return_error;
+                       }
                        usage = SLAP_MR_SUBSTR_ANY;
                        break;
 
                case LDAP_SUBSTRING_FINAL:
+                       if ( ssa.sa_final.bv_val != NULL ) {
+                               rc = LDAP_PROTOCOL_ERROR;
+                               goto return_error;
+                       }
+
                        usage = SLAP_MR_SUBSTR_FINAL;
                        break;
 
                default:
-                       rc = LDAP_PROTOCOL_ERROR;
-
                        Debug( LDAP_DEBUG_FILTER,
                                "  unknown substring choice=%ld\n",
                                (long) tag, 0, 0 );
 
+                       rc = LDAP_PROTOCOL_ERROR;
                        goto return_error;
                }
 
@@ -407,57 +422,28 @@ get_ssa(
                rc = asserted_value_validate_normalize(
                        ssa.sa_desc, ssa.sa_desc->ad_type->sat_equality,
                        usage, &value, &nvalue, text, op->o_tmpmemctx );
-
-               if( rc != LDAP_SUCCESS ) {
-                       goto return_error;
-               }
-
-               rc = LDAP_PROTOCOL_ERROR;
+               if( rc != LDAP_SUCCESS ) goto return_error;
 
                switch ( tag ) {
                case LDAP_SUBSTRING_INITIAL:
                        Debug( LDAP_DEBUG_FILTER, "  INITIAL\n", 0, 0, 0 );
-
-                       if ( ssa.sa_initial.bv_val != NULL
-                               || ssa.sa_any != NULL 
-                               || ssa.sa_final.bv_val != NULL )
-                       {
-                               slap_sl_free( nvalue.bv_val, op->o_tmpmemctx );
-                               goto return_error;
-                       }
-
                        ssa.sa_initial = nvalue;
                        break;
 
                case LDAP_SUBSTRING_ANY:
                        Debug( LDAP_DEBUG_FILTER, "  ANY\n", 0, 0, 0 );
-
-                       if ( ssa.sa_final.bv_val != NULL ) {
-                               slap_sl_free( nvalue.bv_val, op->o_tmpmemctx );
-                               goto return_error;
-                       }
-
                        ber_bvarray_add_x( &ssa.sa_any, &nvalue, op->o_tmpmemctx );
                        break;
 
                case LDAP_SUBSTRING_FINAL:
                        Debug( LDAP_DEBUG_FILTER, "  FINAL\n", 0, 0, 0 );
-
-                       if ( ssa.sa_final.bv_val != NULL ) {
-                               slap_sl_free( nvalue.bv_val, op->o_tmpmemctx );
-                               goto return_error;
-                       }
-
                        ssa.sa_final = nvalue;
                        break;
 
                default:
-                       Debug( LDAP_DEBUG_FILTER,
-                               "  unknown substring type=%ld\n",
-                               (long) tag, 0, 0 );
-
                        assert( 0 );
                        slap_sl_free( nvalue.bv_val, op->o_tmpmemctx );
+                       rc = LDAP_PROTOCOL_ERROR;
 
 return_error:
                        Debug( LDAP_DEBUG_FILTER, "  error=%ld\n",
@@ -477,7 +463,6 @@ return_error:
        }
 
        Debug( LDAP_DEBUG_FILTER, "end get_ssa\n", 0, 0, 0 );
-
        return rc /* LDAP_SUCCESS */ ;
 }
 
@@ -897,7 +882,7 @@ get_simple_vrFilter(
                if( err != LDAP_SUCCESS ) {
                        /* unrecognized attribute description or other error */
                        Debug( LDAP_DEBUG_ANY, 
-                               "get_simple_vrFilter: conn %d unknown "
+                               "get_simple_vrFilter: conn %lu unknown "
                                "attribute type=%s (%d)\n",
                                op->o_connid, type.bv_val, err );
 
index f9cfe6f466137c0110dc178e324dc7c27704b8ae..befc06c76615366fe3a5af19c15aa2ceda57abe0 100644 (file)
@@ -82,6 +82,8 @@ frontend_init( void )
        /* info */
        frontendDB->bd_info = &slap_frontendInfo;
 
+       SLAP_BFLAGS(frontendDB) |= SLAP_BFLAG_FRONTEND;
+
        /* name */
        frontendDB->bd_info->bi_type = "frontend";
 
index 91c699efc719ab54ff0852f6522022d3f22c91fd..510f58b0d0cd430a76f5465d77e9495401db3dda 100644 (file)
@@ -103,18 +103,18 @@ slap_init( int mode, const char *name )
 
        switch ( slapMode & SLAP_MODE ) {
        case SLAP_SERVER_MODE:
+               ldap_pvt_thread_pool_init( &connection_pool,
+                               connection_pool_max, 0);
+
+               /* FALLTHRU */
        case SLAP_TOOL_MODE:
                Debug( LDAP_DEBUG_TRACE,
                        "%s init: initiated %s.\n",     name,
                        (mode & SLAP_MODE) == SLAP_TOOL_MODE ? "tool" : "server",
                        0 );
 
-
                slap_name = name;
 
-               ldap_pvt_thread_pool_init( &connection_pool,
-                               connection_pool_max, 0);
-
                ldap_pvt_thread_mutex_init( &entry2str_mutex );
                ldap_pvt_thread_mutex_init( &replog_mutex );
 
index 44372f596e23fd070c1d58956697c02426f70467..9aec4402b3eaccd34a4ea511ab806f2a99a040c4 100644 (file)
@@ -27,7 +27,7 @@ slap_operational_subschemaSubentry( Backend *be )
        Attribute       *a;
 
        /* The backend wants to take care of it */
-       if ( be && be!= frontendDB && be->be_schemadn.bv_val ) return NULL;
+       if ( be && !SLAP_FRONTEND(be) && be->be_schemadn.bv_val ) return NULL;
 
        a = ch_malloc( sizeof( Attribute ) );
        a->a_desc = slap_schema.si_ad_subschemaSubentry;
index bd356d0c5f521ead71f028843f2a51571bbe1c4a..8318ad7ae68387e25c7d2914159f48b8a87863e6 100644 (file)
@@ -23,6 +23,7 @@ SRCS = overlays.c \
        pcache.c \
        ppolicy.c \
        refint.c \
+       retcode.c \
        rwm.c rwmconf.c rwmdn.c rwmmap.c \
        syncprov.c \
        translucent.c \
@@ -77,6 +78,9 @@ ppolicy.la : ppolicy.lo
 refint.la : refint.lo
        $(LTLINK_MOD) -module -o $@ refint.lo version.lo $(LINK_LIBS)
 
+retcode.la : retcode.lo
+       $(LTLINK_MOD) -module -o $@ retcode.lo version.lo $(LINK_LIBS)
+
 rwm_x.o: rwm.o rwmconf.o rwmdn.o rwmmap.o
        $(LD) -r -o $@ rwm.o rwmconf.o rwmdn.o rwmmap.o
        
index b3da2a206d811ebeb1788ab7a69051c89e51d75b..c17996f706df23ef40da5e5941bbd3640e7389a0 100644 (file)
@@ -670,7 +670,7 @@ static Entry *accesslog_entry( Operation *op, int logop ) {
                attr_merge_one( e, ad_reqType, &lo->word, NULL );
        }
 
-       rdn.bv_len = sprintf( rdn.bv_val, "%d", op->o_connid );
+       rdn.bv_len = sprintf( rdn.bv_val, "%lu", op->o_connid );
        attr_merge_one( e, ad_reqSession, &rdn, NULL );
 
        if ( BER_BVISNULL( &op->o_dn )) 
@@ -1028,6 +1028,7 @@ accesslog_db_destroy(
        log_info *li = on->on_bi.bi_private;
        
        free( li );
+       return LDAP_SUCCESS;
 }
 
 int accesslog_init()
index 965a1e9895c3e7b7f687b040dfd164607f72ac28..6e4e0836a14f6f05c82991bc3793417b0e09c450 100644 (file)
@@ -549,14 +549,23 @@ glue_entry_release_rw (
 )
 {
        BackendDB *b0, b2;
-       int rc;
+       int rc = -1;
 
        b0 = op->o_bd;
        b2 = *op->o_bd;
        b2.bd_info = (BackendInfo *)glue_tool_inst( op->o_bd->bd_info );
        op->o_bd = glue_back_select (&b2, &e->e_nname);
 
-       rc = op->o_bd->be_release( op, e, rw );
+       if ( op->o_bd->be_release ) {
+               rc = op->o_bd->be_release( op, e, rw );
+
+       } else {
+               /* FIXME: mimic be_entry_release_rw
+                * when no be_release() available */
+               /* free entry */
+               entry_free( e );
+               rc = 0;
+       }
        op->o_bd = b0;
        return rc;
 }
@@ -645,7 +654,7 @@ glue_tool_entry_put (
 )
 {
        BackendDB *be, b2;
-       int rc;
+       int rc = NOID;
 
        b2 = *b0;
        b2.bd_info = (BackendInfo *)glue_tool_inst( b0->bd_info );
@@ -656,18 +665,26 @@ glue_tool_entry_put (
                return NOID;
 
        if (!glueBack) {
-               rc = be->be_entry_open (be, glueMode);
-               if (rc != 0)
+               if ( be->be_entry_open ) {
+                       rc = be->be_entry_open (be, glueMode);
+               }
+               if (rc != 0) {
                        return NOID;
+               }
        } else if (be != glueBack) {
                /* If this entry belongs in a different branch than the
                 * previous one, close the current database and open the
                 * new one.
                 */
-               glueBack->be_entry_close (glueBack);
-               rc = be->be_entry_open (be, glueMode);
-               if (rc != 0)
+               if ( glueBack->be_entry_close ) {
+                       glueBack->be_entry_close (glueBack);
+               }
+               if ( be->be_entry_open ) {
+                       rc = be->be_entry_open (be, glueMode);
+               }
+               if (rc != 0) {
                        return NOID;
+               }
        }
        glueBack = be;
        return be->be_entry_put (be, e, text);
@@ -845,7 +862,7 @@ glue_init()
        glue.on_bi.bi_op_search = glue_op_search;
        glue.on_bi.bi_op_modify = glue_op_func;
        glue.on_bi.bi_op_modrdn = glue_op_func;
-       glue.on_bi.bi_op_add = glue_op_func;
+        glue.on_bi.bi_op_add = glue_op_func;
        glue.on_bi.bi_op_delete = glue_op_func;
 
        glue.on_bi.bi_chk_referrals = glue_chk_referrals;
index e83bf7a152ee396459a7125b01f4088e7a383fd8..6c3b81ad09cda529d48f19d87c76f1d52506155b 100644 (file)
@@ -47,6 +47,9 @@ extern int pcache_init();
 #if SLAPD_OVER_REFINT == SLAPD_MOD_STATIC
 extern int refint_init();
 #endif
+#if SLAPD_OVER_RETCODE == SLAPD_MOD_STATIC
+extern int retcode_init();
+#endif
 #if SLAPD_OVER_RWM == SLAPD_MOD_STATIC
 extern int rwm_init();
 #endif
@@ -88,6 +91,9 @@ static struct {
 #if SLAPD_OVER_REFINT == SLAPD_MOD_STATIC
        { "Referential Integrity", refint_init },
 #endif
+#if SLAPD_OVER_RETCODE == SLAPD_MOD_STATIC
+       { "Return Code", retcode_init },
+#endif
 #if SLAPD_OVER_RWM == SLAPD_MOD_STATIC
        { "Rewrite/Remap", rwm_init },
 #endif
index a8d8a2c6b8305b219374a565be7cd45b72a2fc63..5d2d1247e2a914593fb2606462baac76132af1f4 100644 (file)
@@ -1716,7 +1716,7 @@ pc_cf_gen( ConfigArgs *c )
                        break;
                case PC_TEMP:
                        for (i=0; i<cm->numtemplates; i++) {
-                               bv.bv_len = sprintf( c->msg, " %d %d",
+                               bv.bv_len = sprintf( c->msg, " %d %ld",
                                        qm->templates[i].attr_set_index,
                                        qm->templates[i].ttl );
                                bv.bv_len += qm->templates[i].querystr.bv_len + 2;
index 9941f865dca0888bed07f5e5c839b38d04eb98f5..4b29520517dfc4e7b08e6e7d73abfa5102bbc7fb 100644 (file)
@@ -228,6 +228,9 @@ account_locked( Operation *op, Entry *e,
                        struct berval bv;
                        Modifications *m;
 
+                       if (!pp->pwdLockoutDuration)
+                               return 1;
+
                        if ((then = parse_time( vals[0].bv_val )) == (time_t)0)
                                return 1;
 
@@ -413,12 +416,9 @@ password_scheme( struct berval *cred, struct berval *sch )
 
        for(e = 1; cred->bv_val[e] && cred->bv_val[e] != '}'; e++);
        if (cred->bv_val[e]) {
-               char *sc = ch_calloc( sizeof(char), e + 2);
-               sc[e + 1] = '\0'; /* terminate string */
-               strncpy( sc, cred->bv_val, e + 1);
-               e = lutil_passwd_scheme( sc );
-               free( sc );
-               if (e && sch) {
+               int rc;
+               rc = lutil_passwd_scheme( cred->bv_val );
+               if (rc && sch) {
                        sch->bv_val = cred->bv_val;
                        sch->bv_len = e;
                        return LDAP_SUCCESS;
@@ -625,9 +625,9 @@ make_pwd_history_value( char *timebuf, struct berval *bv, Attribute *pa )
        int nlen;
 
        snprintf( str, MAX_PWD_HISTORY_SZ,
-                 "%s#%s#%d#", timebuf,
+                 "%s#%s#%lu#", timebuf,
                  pa->a_desc->ad_type->sat_syntax->ssyn_oid,
-                 pa->a_nvals[0].bv_len );
+                 (unsigned long) pa->a_nvals[0].bv_len );
        str[MAX_PWD_HISTORY_SZ-1] = 0;
        nlen = strlen(str);
 
index 85d73d2ad07e030d694d63944a1913689a5f2595..e485b063480f7c6e804086aa69c7f4231279f181 100644 (file)
@@ -228,6 +228,32 @@ cleanup_attr:;
        return SLAP_CB_CONTINUE;
 }
 
+#ifdef ENABLE_REWRITE
+static int
+rwm_conn_init( BackendDB *be, Connection *conn )
+{
+       slap_overinst           *on = (slap_overinst *) be->bd_info;
+       struct ldaprwmap        *rwmap = 
+                       (struct ldaprwmap *)on->on_bi.bi_private;
+
+       ( void )rewrite_session_init( rwmap->rwm_rw, conn );
+
+       return SLAP_CB_CONTINUE;
+}
+
+static int
+rwm_conn_destroy( BackendDB *be, Connection *conn )
+{
+       slap_overinst           *on = (slap_overinst *) be->bd_info;
+       struct ldaprwmap        *rwmap = 
+                       (struct ldaprwmap *)on->on_bi.bi_private;
+
+       ( void )rewrite_session_delete( rwmap->rwm_rw, conn );
+
+       return SLAP_CB_CONTINUE;
+}
+#endif /* ENABLE_REWRITE */
+
 static int
 rwm_op_bind( Operation *op, SlapReply *rs )
 {
@@ -237,9 +263,6 @@ rwm_op_bind( Operation *op, SlapReply *rs )
        int                     rc;
 
 #ifdef ENABLE_REWRITE
-       ( void )rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
-       ( void )rewrite_session_init( rwmap->rwm_rw, op->o_conn );
-
        rc = rwm_op_dn_massage( op, rs, "bindDN" );
 #else /* ! ENABLE_REWRITE */
        rc = 1;
@@ -583,6 +606,36 @@ rwm_op_modrdn( Operation *op, SlapReply *rs )
        return SLAP_CB_CONTINUE;
 }
 
+static slap_callback   rwm_cb;
+
+static void
+rwm_keyfree(
+       void            *key,
+       void            *data )
+{
+       ber_memfree_x( data, NULL );
+}
+
+static slap_callback *
+rwm_callback_get( Operation *op )
+{
+       void            *data = NULL;
+
+       if ( op->o_threadctx == NULL ) {
+               return &rwm_cb;
+       }
+
+       ldap_pvt_thread_pool_getkey( op->o_threadctx,
+                       rwm_keyfree, &data, NULL );
+       if ( data == NULL ) {
+               data = ch_calloc( sizeof( slap_callback ), 1 );
+               ldap_pvt_thread_pool_setkey( op->o_threadctx,
+                               rwm_keyfree, data, rwm_keyfree );
+       }
+
+       return (slap_callback *)data;
+}
+
 static int
 rwm_swap_attrs( Operation *op, SlapReply *rs )
 {
@@ -594,18 +647,6 @@ rwm_swap_attrs( Operation *op, SlapReply *rs )
        return SLAP_CB_CONTINUE;
 }
 
-static int rwm_freeself( Operation *op, SlapReply *rs )
-{
-       if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_RESULT ) {
-               assert( op->o_callback );
-
-               op->o_tmpfree( op->o_callback, op->o_tmpmemctx );
-               op->o_callback = NULL;
-       }
-
-       return SLAP_CB_CONTINUE;
-}
-
 static int
 rwm_op_search( Operation *op, SlapReply *rs )
 {
@@ -619,7 +660,7 @@ rwm_op_search( Operation *op, SlapReply *rs )
        struct berval           fstr = BER_BVNULL;
        Filter                  *f = NULL;
 
-       slap_callback           *cb;
+       slap_callback           *cb = NULL;
        AttributeName           *an = NULL;
 
        char                    *text = NULL;
@@ -679,15 +720,10 @@ rwm_op_search( Operation *op, SlapReply *rs )
                goto error_return;
        }
 
-       cb = (slap_callback *) op->o_tmpcalloc( sizeof( slap_callback ),
-                       1, op->o_tmpmemctx );
-       if ( cb == NULL ) {
-               rc = LDAP_NO_MEMORY;
-               goto error_return;
-       }
+       cb = rwm_callback_get( op );
 
        cb->sc_response = rwm_swap_attrs;
-       cb->sc_cleanup = rwm_freeself;
+       cb->sc_cleanup = NULL;
        cb->sc_private = (void *)op->ors_attrs;
        cb->sc_next = op->o_callback;
 
@@ -1482,6 +1518,11 @@ rwm_init(void)
        rwm.on_bi.bi_operational = rwm_operational;
        rwm.on_bi.bi_chk_referrals = 0 /* rwm_chk_referrals */ ;
 
+#ifdef ENABLE_REWRITE
+       rwm.on_bi.bi_connection_init = rwm_conn_init;
+       rwm.on_bi.bi_connection_destroy = rwm_conn_destroy;
+#endif /* ENABLE_REWRITE */
+
        rwm.on_response = rwm_response;
 
        return overlay_register( &rwm );
index bfa40a1de139ac0224b044084bdeca59e9560bf1..c201744ae08c9afa1d690193f666d6879b86b67d 100644 (file)
@@ -450,15 +450,9 @@ rwm_int_filter_map_rewrite(
                        vtmp,
                        tmp;
        static struct berval
-#if 0
-                       ber_bvfalse = BER_BVC( "(?=false)" ),
-#endif
                        /* better than nothing... */
                        ber_bvfalse = BER_BVC( "(!(objectClass=*))" ),
                        ber_bvtf_false = BER_BVC( "(|)" ),
-#if 0
-                       ber_bvtrue = BER_BVC( "(?=true)" ),
-#endif
                        /* better than nothing... */
                        ber_bvtrue = BER_BVC( "(objectClass=*)" ),
                        ber_bvtf_true = BER_BVC( "(&)" ),
@@ -678,9 +672,12 @@ rwm_int_filter_map_rewrite(
                case LDAP_COMPARE_FALSE:
                        if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
                                tmp = ber_bvtf_false;
-                       } else {
-                               tmp = ber_bvfalse;
+                               break;
                        }
+                       /* fallthru */
+
+               case SLAPD_COMPARE_UNDEFINED:
+                       tmp = ber_bvfalse;
                        break;
 
                case LDAP_COMPARE_TRUE:
@@ -691,10 +688,6 @@ rwm_int_filter_map_rewrite(
                        }
                        break;
                        
-               case SLAPD_COMPARE_UNDEFINED:
-                       tmp = ber_bvundefined;
-                       break;
-                       
                default:
                        tmp = ber_bverror;
                        break;
index 74d428c4bc5b21277b6c1a78b7d3c27f2bdff3f3..a8c6398243d8519eb7b7458c0377ceb5857f3255 100644 (file)
@@ -548,7 +548,7 @@ syncprov_findcsn( Operation *op, int mode )
        SlapReply frs = { REP_RESULT };
        char buf[LDAP_LUTIL_CSNSTR_BUFSIZE + STRLENOF("(entryCSN<=)")];
        char cbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
-       struct berval fbuf, maxcsn;
+       struct berval maxcsn;
        Filter cf, af;
 #ifdef LDAP_COMP_MATCH
        AttributeAssertion eq = { NULL, BER_BVNULL, NULL };
@@ -572,7 +572,6 @@ syncprov_findcsn( Operation *op, int mode )
        /* We want pure entries, not referrals */
        fop.o_managedsait = SLAP_CONTROL_CRITICAL;
 
-       fbuf.bv_val = buf;
        cf.f_ava = &eq;
        cf.f_av_desc = slap_schema.si_ad_entryCSN;
        cf.f_next = NULL;
@@ -581,13 +580,13 @@ syncprov_findcsn( Operation *op, int mode )
        fop.ors_limit = NULL;
        fop.ors_tlimit = SLAP_NO_LIMIT;
        fop.ors_filter = &cf;
-       fop.ors_filterstr = fbuf;
+       fop.ors_filterstr.bv_val = buf;
 
        switch( mode ) {
        case FIND_MAXCSN:
                cf.f_choice = LDAP_FILTER_GE;
                cf.f_av_value = si->si_ctxcsn;
-               fbuf.bv_len = sprintf( buf, "(entryCSN>=%s)",
+               fop.ors_filterstr.bv_len = sprintf( buf, "(entryCSN>=%s)",
                        cf.f_av_value.bv_val );
                fop.ors_attrsonly = 0;
                fop.ors_attrs = csn_anlist;
@@ -601,7 +600,7 @@ syncprov_findcsn( Operation *op, int mode )
        case FIND_CSN:
                cf.f_choice = LDAP_FILTER_LE;
                cf.f_av_value = srs->sr_state.ctxcsn;
-               fbuf.bv_len = sprintf( buf, "(entryCSN<=%s)",
+               fop.ors_filterstr.bv_len = sprintf( buf, "(entryCSN<=%s)",
                        cf.f_av_value.bv_val );
                fop.ors_attrsonly = 1;
                fop.ors_attrs = slap_anlist_no_attrs;
@@ -1075,7 +1074,7 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
                }
        }
        ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex );
-done:
+
        if ( op->o_tag != LDAP_REQ_ADD && e ) {
                op->o_bd->bd_info = (BackendInfo *)on->on_info;
                be_entry_release_rw( op, e, 0 );
@@ -2114,6 +2113,18 @@ typedef struct thread_keys {
 /* A fake thread context */
 static thread_keys thrctx[MAXKEYS];
 
+/* ITS#3456 we cannot run this search on the main thread, must use a
+ * child thread in order to insure we have a big enough stack.
+ */
+static void *
+syncprov_db_otask(
+       void *ptr
+)
+{
+       syncprov_findcsn( ptr, FIND_MAXCSN );
+       return NULL;
+}
+
 /* Read any existing contextCSN from the underlying db.
  * Then search for any entries newer than that. If no value exists,
  * just generate it. Cache whatever result.
@@ -2155,6 +2166,8 @@ syncprov_db_open(
                slap_schema.si_ad_contextCSN, 0, &e );
 
        if ( e ) {
+               ldap_pvt_thread_t tid;
+
                a = attr_find( e->e_attrs, slap_schema.si_ad_contextCSN );
                if ( a ) {
                        si->si_ctxcsn.bv_len = a->a_nvals[0].bv_len;
@@ -2170,7 +2183,8 @@ syncprov_db_open(
                op->o_req_dn = be->be_suffix[0];
                op->o_req_ndn = be->be_nsuffix[0];
                op->ors_scope = LDAP_SCOPE_SUBTREE;
-               syncprov_findcsn( op, FIND_MAXCSN );
+               ldap_pvt_thread_create( &tid, 0, syncprov_db_otask, op );
+               ldap_pvt_thread_join( tid, NULL );
        } else if ( SLAP_SYNC_SHADOW( op->o_bd )) {
                /* If we're also a consumer, and we didn't find the context entry,
                 * then don't generate anything, wait for our provider to send it
@@ -2185,11 +2199,10 @@ syncprov_db_open(
        }
 
        /* If our ctxcsn is different from what was read from the root
-        * entry, write the new value out.
+        * entry, make sure we do a checkpoint on close
         */
        if ( strcmp( si->si_ctxcsnbuf, ctxcsnbuf )) {
-               SlapReply rs = {REP_RESULT};
-               syncprov_checkpoint( op, &rs, on );
+               si->si_numops++;
        }
 
 out:
index 0917bd2273a7216ce47e897e28a874c10b467228..db44ffe17a9fe2d5de7585b4e5c2d027a697acc7 100644 (file)
@@ -510,8 +510,10 @@ static int slapd_crypt( const char *key, const char *salt, char **hash )
                if ( hash ) {
                        *hash = ber_strdup( cr );
                        rc = LUTIL_PASSWD_OK;
+
+               } else {
+                       rc = strcmp( salt, cr ) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
                }
-               rc = strcmp( salt, cr ) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
        }
 
        ldap_pvt_thread_mutex_unlock( &passwd_mutex );
index ee12a59ec38358731c2a21258efdd3b08b1e72c4..b457ea2b043c9c0684f9f9d71f61444038c75688 100644 (file)
@@ -74,6 +74,8 @@ LDAP_SLAPD_F (int) acl_init LDAP_P(( void ));
 /*
  * aclparse.c
  */
+LDAP_SLAPD_V (char *) style_strings[];
+
 LDAP_SLAPD_F (void) parse_acl LDAP_P(( Backend *be,
        const char *fname, int lineno,
        int argc, char **argv, int pos ));
index 3b3cb12f0cccc407de49ba3b79a4bfac73b870e2..64389ccd170d43bbebdc56d775e95c7c617214b2 100644 (file)
@@ -324,7 +324,7 @@ slap_discover_feature(
        char            *attrs[ 2 ] = { NULL, NULL };
 
        ber_str2bv( val, 0, 0, &bv_val );
-       attrs[ 0 ] = attr;
+       attrs[ 0 ] = (char *) attr;
 
        rc = ldap_initialize( &ld, uri );
        if ( rc != LDAP_SUCCESS ) {
index 10b17ca62f33e0d7d0ab3574b0c81660014ab697..52701bab78a630120d40757b4187f795bc87893e 100644 (file)
@@ -163,6 +163,8 @@ typedef struct lookup_info {
 
 static slap_response sasl_ap_lookup;
 
+static struct berval sc_cleartext = BER_BVC("{CLEARTEXT}");
+
 static int
 sasl_ap_lookup( Operation *op, SlapReply *rs )
 {
@@ -210,6 +212,34 @@ sasl_ap_lookup( Operation *op, SlapReply *rs )
                        sl->list[i].name );
                }
                for ( bv = a->a_vals; bv->bv_val; bv++ ) {
+                       /* ITS#3846 don't give hashed passwords to SASL */
+                       if ( ad == slap_schema.si_ad_userPassword &&
+                               bv->bv_val[0] == '{' ) {
+                               rc = lutil_passwd_scheme( bv->bv_val );
+                               if ( rc ) {
+                                       /* If it's not a recognized scheme, just assume it's
+                                        * a cleartext password that happened to include brackets.
+                                        *
+                                        * If it's a recognized scheme, skip this value, unless the
+                                        * scheme is {CLEARTEXT}. In that case, skip over the
+                                        * scheme name and use the remainder. If there is nothing
+                                        * past the scheme name, skip this value.
+                                        */
+#ifdef SLAPD_CLEARTEXT
+                                       if ( !strncasecmp( bv->bv_val, sc_cleartext.bv_val,
+                                               sc_cleartext.bv_len )) {
+                                               struct berval cbv;
+                                               cbv.bv_len = bv->bv_len - sc_cleartext.bv_len;
+                                               if ( cbv.bv_len ) {
+                                                       cbv.bv_val = bv->bv_val + sc_cleartext.bv_len;
+                                                       sl->sparams->utils->prop_set( sl->sparams->propctx,
+                                                               sl->list[i].name, cbv.bv_val, cbv.bv_len );
+                                               }
+                                       }
+#endif
+                                       continue;
+                               }
+                       }
                        sl->sparams->utils->prop_set( sl->sparams->propctx,
                                sl->list[i].name, bv->bv_val, bv->bv_len );
                }
@@ -1495,10 +1525,11 @@ int slap_sasl_getdn( Connection *conn, Operation *op, struct berval *id,
        assert( conn );
        assert( id );
 
-       Debug( LDAP_DEBUG_ARGS, "slap_sasl_getdn: conn %d id=%s [len=%d]\n", 
+       Debug( LDAP_DEBUG_ARGS, "slap_sasl_getdn: conn %lu id=%s [len=%lu]\n", 
                conn->c_connid,
                BER_BVISNULL( id ) ? "NULL" : ( BER_BVISEMPTY( id ) ? "<empty>" : id->bv_val ),
-               BER_BVISNULL( id ) ? 0 : ( BER_BVISEMPTY( id ) ? 0 : id->bv_len ) );
+               BER_BVISNULL( id ) ? 0 : ( BER_BVISEMPTY( id ) ? 0 :
+                                          (unsigned long) id->bv_len ) );
 
        if ( !op ) {
                op = conn->c_sasl_bindop;
index 8d3feb8874eebf57f037044e92853e069c87527d..0ce73bb9b399ef77e71abbfb713e3ebb4d0b0669 100644 (file)
@@ -2321,7 +2321,7 @@ integerBitAndMatch(
                return LDAP_CONSTRAINT_VIOLATION;
        }
 
-       *matchp = (lValue & lAssertedValue) ? 0 : 1;
+       *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
        return LDAP_SUCCESS;
 }
 
@@ -2352,7 +2352,7 @@ integerBitOrMatch(
                return LDAP_CONSTRAINT_VIOLATION;
        }
 
-       *matchp = (lValue | lAssertedValue) ? 0 : -1;
+       *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
        return LDAP_SUCCESS;
 }
 
index d065c57ec9166a3cb99da6699810de0eb4136513..1f6bd267f5b80b0d2052ae8928d6f8061023e1d9 100644 (file)
@@ -633,7 +633,7 @@ print_slheap(int level, void *ctx)
                Debug(level, "free list:\n", 0, 0, 0);
                so = LDAP_LIST_FIRST(&sh->sh_free[i-order_start]);
                while (so) {
-                       Debug(level, "%x\n",so->so_ptr, 0, 0);
+                       Debug(level, "%lx\n", (unsigned long) so->so_ptr, 0, 0);
                        so = LDAP_LIST_NEXT(so, so_link);
                }
        }
index c79ef4c1c7a72649cbe5b685839d3b1a04dab81a..a3c11195d80f78bf4fd4815d6bc8c0844134d6c8 100644 (file)
@@ -1440,6 +1440,7 @@ typedef struct slap_acl {
        regex_t         acl_dn_re;
        struct berval   acl_dn_pat;
        AttributeName   *acl_attrs;
+       MatchingRule    *acl_attrval_mr;
        slap_style_t    acl_attrval_style;
        regex_t         acl_attrval_re;
        struct berval   acl_attrval;
@@ -2110,6 +2111,7 @@ 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_FRONTEND                    0x0004U /* the frontendDB */
 #define SLAP_BFLAG_NOLASTMODCMD                0x0010U
 #define SLAP_BFLAG_INCREMENT           0x0100U
 #define SLAP_BFLAG_ALIASES                     0x1000U
@@ -2120,6 +2122,7 @@ 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_FRONTEND(be)      (SLAP_BFLAGS(be) & SLAP_BFLAG_FRONTEND)
 #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)
@@ -2426,7 +2429,7 @@ typedef struct slap_op {
 #define get_domainScope(op)                            (0)
 #endif
 
-#ifdef LDAP_CONTROL_X_TREE_DELETE
+#ifdef SLAP_CONTROL_X_TREE_DELETE
 #define        o_tree_delete   o_ctrlflag[slap_cids.sc_treeDelete]
 #define get_treeDelete(op)                             ((int)(op)->o_tree_delete)
 #else
index ca7e8c45da3d21ad49a33879f603a739a847e0b5..6689fb41b714544f31173a508eb8ca2055681835 100644 (file)
@@ -2308,7 +2308,7 @@ slapi_timer_get_time( char *label )
 {
 #ifdef LDAP_SLAPI
        unsigned long start = slapi_timer_current_time();
-       printf("%10ld %10ld usec %s\n", start, 0, label);
+       printf("%10ld %10d usec %s\n", start, 0, label);
        return start;
 #else /* LDAP_SLAPI */
        return 0;
index 118e7771b53c6af08242f225324eb9e0f33bbc09..f7efaf86fc2c93084cd90fb8627a375ea85dbde8 100644 (file)
@@ -2240,21 +2240,22 @@ syncinfo_free( syncinfo_t *sie )
 /* NOTE: used & documented in slapd.conf(5) */
 #define IDSTR                  "rid"
 #define PROVIDERSTR            "provider"
-#define TYPESTR                        "type"
-#define INTERVALSTR            "interval"
-#define SEARCHBASESTR          "searchbase"
+#define SCHEMASTR              "schemachecking"
 #define FILTERSTR              "filter"
+#define SEARCHBASESTR          "searchbase"
 #define SCOPESTR               "scope"
-#define ATTRSSTR               "attrs"
 #define ATTRSONLYSTR           "attrsonly"
+#define ATTRSSTR               "attrs"
+#define TYPESTR                        "type"
+#define INTERVALSTR            "interval"
+#define RETRYSTR               "retry"
 #define SLIMITSTR              "sizelimit"
 #define TLIMITSTR              "timelimit"
-#define SCHEMASTR              "schemachecking"
 
 /* FIXME: undocumented */
 #define OLDAUTHCSTR            "bindprincipal"
 #define EXATTRSSTR             "exattrs"
-#define RETRYSTR               "retry"
+#define MANAGEDSAITSTR         "manageDSAit"
 
 /* FIXME: unused */
 #define LASTMODSTR             "lastmod"
@@ -2263,7 +2264,6 @@ syncinfo_free( syncinfo_t *sie )
 #define LMREQSTR               "req"
 #define SRVTABSTR              "srvtab"
 #define SUFFIXSTR              "suffix"
-#define MANAGEDSAITSTR         "manageDSAit"
 
 /* mandatory */
 #define GOT_ID                 0x0001
@@ -2278,11 +2278,13 @@ static struct {
 } scopes[] = {
        { BER_BVC("base"), LDAP_SCOPE_BASE },
        { BER_BVC("one"), LDAP_SCOPE_ONELEVEL },
+       { BER_BVC("onelevel"), LDAP_SCOPE_ONELEVEL },   /* OpenLDAP extension */
 #ifdef LDAP_SCOPE_SUBORDINATE
        { BER_BVC("children"), LDAP_SCOPE_SUBORDINATE },
-       { BER_BVC("subordinate"), 0 },
+       { BER_BVC("subordinate"), LDAP_SCOPE_SUBORDINATE },
 #endif
        { BER_BVC("sub"), LDAP_SCOPE_SUBTREE },
+       { BER_BVC("subtree"), LDAP_SCOPE_SUBTREE },     /* OpenLDAP extension */
        { BER_BVNULL, 0 }
 };
 
@@ -2357,9 +2359,7 @@ parse_syncrepl_line(
                        int j;
                        val = cargv[ i ] + STRLENOF( SCOPESTR "=" );
                        for ( j=0; !BER_BVISNULL(&scopes[j].key); j++ ) {
-                               if (!strncasecmp( val, scopes[j].key.bv_val,
-                                       scopes[j].key.bv_len )) {
-                                       while (!scopes[j].val) j--;
+                               if (!strcasecmp( val, scopes[j].key.bv_val )) {
                                        si->si_scope = scopes[j].val;
                                        break;
                                }
@@ -2663,7 +2663,7 @@ syncrepl_unparse( syncinfo_t *si, struct berval *bv )
 
        bindconf_unparse( &si->si_bindconf, &bc );
        ptr = buf;
-       ptr += sprintf( ptr, IDSTR "=%03d " PROVIDERSTR "=%s",
+       ptr += sprintf( ptr, IDSTR "=%03ld " PROVIDERSTR "=%s",
                si->si_rid, si->si_provideruri.bv_val );
        if ( !BER_BVISNULL( &bc )) {
                ptr = lutil_strcopy( ptr, bc.bv_val );
@@ -2737,11 +2737,11 @@ syncrepl_unparse( syncinfo_t *si, struct berval *bv )
                for (i=0; si->si_retryinterval[i]; i++) {
                        if ( space ) *ptr++ = ' ';
                        space = 1;
-                       ptr += sprintf( ptr, "%d ", si->si_retryinterval[i] );
+                       ptr += sprintf( ptr, "%ld ", (long) si->si_retryinterval[i] );
                        if ( si->si_retrynum_init[i] == -1 )
                                *ptr++ = '+';
                        else
-                               ptr += sprintf( ptr, "%d", si->si_retrynum_init );
+                               ptr += sprintf( ptr, "%d", si->si_retrynum_init[i] );
                }
                *ptr++ = '"';
        }