Commit 332fcf80 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Sync with HEAD

parent 899b9f01
......@@ -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;
}
......
......@@ -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"
......
......@@ -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") };
......
......@@ -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 );
......
......@@ -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 );
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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? */
......
......@@ -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 )
......
......@@ -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 );
......
......@@ -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 */
......
......@@ -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: