Add ACL state recording to avoid multiple evaluation of

value-independent access controls.
This commit is contained in:
Kurt Zeilenga 2002-02-09 05:14:17 +00:00
parent ffa4b26343
commit 32fb8b0bff
19 changed files with 216 additions and 102 deletions

View file

@ -50,7 +50,9 @@ static slap_control_t acl_mask(
Entry *e,
AttributeDescription *desc,
struct berval *val,
regmatch_t *matches );
regmatch_t *matches,
int count,
AccessControlState *state );
#ifdef SLAPD_ACI_ENABLED
static int aci_mask(
@ -106,8 +108,10 @@ access_allowed(
Entry *e,
AttributeDescription *desc,
struct berval *val,
slap_access_t access )
slap_access_t access,
AccessControlState *state )
{
int ret = 1;
int count;
AccessControl *a;
#ifdef LDAP_DEBUG
@ -126,6 +130,19 @@ access_allowed(
assert( attr != NULL );
if( state && state->as_recorded ) {
if( state->as_recorded & ACL_STATE_RECORDED_NV &&
val == NULL )
{
return state->as_result;
} else if ( state->as_recorded & ACL_STATE_RECORDED_VD &&
val != NULL && state->as_vd_acl == NULL )
{
return state->as_result;
}
}
#ifdef NEW_LOGGING
LDAP_LOG(( "acl", LDAP_LEVEL_ENTRY,
"access_allowed: conn %d %s access to \"%s\" \"%s\" requested\n",
@ -138,7 +155,7 @@ access_allowed(
if ( op == NULL ) {
/* no-op call */
return 1;
goto done;
}
if ( be == NULL ) be = &backends[0];
@ -155,7 +172,7 @@ access_allowed(
"<= root access granted\n",
0, 0, 0 );
#endif
return 1;
goto done;
}
/*
@ -176,7 +193,7 @@ access_allowed(
" %s access granted\n",
attr, 0, 0 );
#endif
return 1;
goto done;
}
/* use backend default access if no backend acls */
@ -192,7 +209,8 @@ access_allowed(
access2str( access ),
be->be_dfltaccess >= access ? "granted" : "denied", op->o_dn.bv_val );
#endif
return be->be_dfltaccess >= access;
ret = be->be_dfltaccess >= access;
goto done;
#ifdef notdef
/* be is always non-NULL */
@ -209,29 +227,45 @@ access_allowed(
access2str( access ),
global_default_access >= access ? "granted" : "denied", op->o_dn.bv_val );
#endif
return global_default_access >= access;
ret = global_default_access >= access;
goto done;
#endif
}
ACL_INIT(mask);
memset(matches, '\0', sizeof(matches));
ret = 0;
control = ACL_BREAK;
a = NULL;
count = 0;
while((a = acl_get( a, &count, be, op, e, desc, MAXREMATCHES, matches )) != NULL)
if( state && ( state->as_recorded & ACL_STATE_RECORDED_VD )) {
assert( state->as_vd_acl != NULL );
a = state->as_vd_acl;
mask = state->as_vd_acl_mask;
count = state->as_vd_acl_count;
AC_MEMCPY( matches, state->as_vd_acl_matches,
sizeof(matches) );
goto vd_access;
} else {
a = NULL;
ACL_INIT(mask);
count = 0;
memset(matches, '\0', sizeof(matches));
}
while((a = acl_get( a, &count, be, op, e, desc,
MAXREMATCHES, matches )) != NULL)
{
int i;
for (i = 0; i < MAXREMATCHES && matches[i].rm_so > 0; i++) {
#ifdef NEW_LOGGING
LDAP_LOG(( "acl", LDAP_LEVEL_DETAIL1,
"access_allowed: conn %d match[%d]: %d %d ",
conn->c_connid, i, (int)matches[i].rm_so, (int)matches[i].rm_eo ));
"access_allowed: conn %d match[%d]: %d %d ",
conn->c_connid, i,
(int)matches[i].rm_so, (int)matches[i].rm_eo ));
#else
Debug( LDAP_DEBUG_ACL, "=> match[%d]: %d %d ", i,
(int)matches[i].rm_so, (int)matches[i].rm_eo );
(int)matches[i].rm_so, (int)matches[i].rm_eo );
#endif
if( matches[i].rm_so <= matches[0].rm_eo ) {
int n;
@ -246,8 +280,9 @@ access_allowed(
#endif
}
vd_access:
control = acl_mask( a, &mask, be, conn, op,
e, desc, val, matches );
e, desc, val, matches, count, state );
if ( control != ACL_BREAK ) {
break;
@ -259,14 +294,14 @@ access_allowed(
if ( ACL_IS_INVALID( mask ) ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "acl", LDAP_LEVEL_DETAIL1,
"access_allowed: conn %d \"%s\" (%s) invalid!\n",
conn->c_connid, e->e_dn, attr ));
"access_allowed: conn %d \"%s\" (%s) invalid!\n",
conn->c_connid, e->e_dn, attr ));
#else
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: \"%s\" (%s) invalid!\n",
e->e_dn, attr, 0 );
#endif
ACL_INIT( mask );
ACL_INIT(mask);
} else if ( control == ACL_BREAK ) {
#ifdef NEW_LOGGING
@ -276,16 +311,17 @@ access_allowed(
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: no more rules\n", 0, 0, 0);
#endif
ACL_INIT( mask );
goto done;
}
#ifdef NEW_LOGGING
LDAP_LOG(( "acl", LDAP_LEVEL_ENTRY,
"access_allowed: conn %d %s access %s by %s\n",
conn->c_connid,
access2str( access ),
ACL_GRANT( mask, access ) ? "granted" : "denied",
accessmask2str( mask, accessmaskbuf ) ));
"access_allowed: conn %d %s access %s by %s\n",
conn->c_connid,
access2str( access ),
ACL_GRANT( mask, access ) ? "granted" : "denied",
accessmask2str( mask, accessmaskbuf ) ));
#else
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: %s access %s by %s\n",
@ -293,7 +329,15 @@ access_allowed(
ACL_GRANT(mask, access) ? "granted" : "denied",
accessmask2str( mask, accessmaskbuf ) );
#endif
return ACL_GRANT(mask, access);
ret = ACL_GRANT(mask, access);
done:
if( state != NULL ) {
state->as_recorded |= ACL_STATE_RECORDED;
state->as_result = ret;
}
return ret;
}
/*
@ -452,6 +496,20 @@ acl_get(
return( NULL );
}
/*
* Record value-dependent access control state
*/
#define ACL_RECORD_VALUE_STATE do { \
if( state && !( state->as_recorded & ACL_STATE_RECORDED_VD )) { \
state->as_recorded |= ACL_STATE_RECORDED_VD; \
state->as_vd_acl = a; \
AC_MEMCPY( state->as_vd_acl_matches, matches, \
sizeof( state->as_vd_acl_matches )) ; \
state->as_vd_acl_count = count; \
state->as_vd_access = b; \
state->as_vd_access_count = i; \
} \
} while( 0 )
/*
* acl_mask - modifies mask based upon the given acl and the
@ -472,10 +530,12 @@ acl_mask(
Entry *e,
AttributeDescription *desc,
struct berval *val,
regmatch_t *matches
)
regmatch_t *matches,
int count,
AccessControlState *state )
{
int i, odnlen, patlen;
int vd_recorded = 0;
Access *b;
#ifdef LDAP_DEBUG
char accessmaskbuf[ACCESSMASK_MAXLEN];
@ -512,7 +572,18 @@ acl_mask(
accessmask2str( *mask, accessmaskbuf ) );
#endif
for ( i = 1, b = a->acl_access; b != NULL; b = b->a_next, i++ ) {
if( state && ( state->as_recorded & ACL_STATE_RECORDED_VD )
&& state->as_vd_acl == a )
{
b = state->as_vd_access;
i = state->as_vd_access_count;
} else {
b = a->acl_access;
i = 1;
}
for ( ; b != NULL; b = b->a_next, i++ ) {
slap_mask_t oldmask, modmask;
ACL_INVALIDATE( modmask );
@ -750,11 +821,15 @@ acl_mask(
/* no dnattr match, check if this is a self clause */
if ( ! b->a_dn_self )
continue;
ACL_RECORD_VALUE_STATE;
/* this is a self clause, check if the target is an
* attribute.
*/
if ( val == NULL )
continue;
/* target is attribute, check if the attribute value
* is the op dn.
*/
@ -892,6 +967,8 @@ acl_mask(
continue;
}
ACL_RECORD_VALUE_STATE;
/* start out with nothing granted, nothing denied */
ACL_INIT(tgrant);
ACL_INIT(tdeny);
@ -1086,6 +1163,9 @@ acl_check_modlist(
}
for ( ; mlist != NULL; mlist = mlist->sml_next ) {
static AccessControlState state_init = ACL_STATE_INIT;
AccessControlState state;
/*
* no-user-modification operational attributes are ignored
* by ACL_WRITE checking as any found here are not provided
@ -1104,6 +1184,8 @@ acl_check_modlist(
continue;
}
state = state_init;
switch ( mlist->sml_op ) {
case LDAP_MOD_REPLACE:
/*
@ -1112,7 +1194,7 @@ acl_check_modlist(
* This prevents abuse from selfwriters.
*/
if ( ! access_allowed( be, conn, op, e,
mlist->sml_desc, NULL, ACL_WRITE ) )
mlist->sml_desc, NULL, ACL_WRITE, &state ) )
{
return( 0 );
}
@ -1126,7 +1208,7 @@ acl_check_modlist(
for ( bv = mlist->sml_bvalues; bv->bv_val != NULL; bv++ ) {
if ( ! access_allowed( be, conn, op, e,
mlist->sml_desc, bv, ACL_WRITE ) )
mlist->sml_desc, bv, ACL_WRITE, &state ) )
{
return( 0 );
}
@ -1136,7 +1218,7 @@ acl_check_modlist(
case LDAP_MOD_DELETE:
if ( mlist->sml_bvalues == NULL ) {
if ( ! access_allowed( be, conn, op, e,
mlist->sml_desc, NULL, ACL_WRITE ) )
mlist->sml_desc, NULL, ACL_WRITE, NULL ) )
{
return( 0 );
}
@ -1144,7 +1226,7 @@ acl_check_modlist(
}
for ( bv = mlist->sml_bvalues; bv->bv_val != NULL; bv++ ) {
if ( ! access_allowed( be, conn, op, e,
mlist->sml_desc, bv, ACL_WRITE ) )
mlist->sml_desc, bv, ACL_WRITE, &state ) )
{
return( 0 );
}

View file

@ -173,7 +173,7 @@ retry: /* transaction retry */
}
rc = access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE );
children, NULL, ACL_WRITE, NULL );
switch( opinfo.boi_err ) {
case DB_LOCK_DEADLOCK:
@ -253,7 +253,7 @@ retry: /* transaction retry */
/* check parent for "children" acl */
rc = access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE );
children, NULL, ACL_WRITE, NULL );
p = NULL;
switch( opinfo.boi_err ) {

View file

@ -37,6 +37,7 @@ bdb_attribute(
Attribute *attr;
BerVarray v;
const char *entry_at_name = entry_at->ad_cname.bv_val;
AccessControlState acl_state = ACL_STATE_INIT;
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_ARGS,
@ -142,8 +143,8 @@ bdb_attribute(
}
if (conn != NULL && op != NULL
&& access_allowed(be, conn, op, e, slap_schema.si_ad_entry,
NULL, ACL_READ) == 0)
&& access_allowed( be, conn, op, e, slap_schema.si_ad_entry,
NULL, ACL_READ, &acl_state ) == 0 )
{
rc = LDAP_INSUFFICIENT_ACCESS;
goto return_results;
@ -163,7 +164,8 @@ bdb_attribute(
}
if (conn != NULL && op != NULL
&& access_allowed(be, conn, op, e, entry_at, NULL, ACL_READ) == 0)
&& access_allowed( be, conn, op, e, entry_at, NULL, ACL_READ,
&acl_state ) == 0 )
{
rc = LDAP_INSUFFICIENT_ACCESS;
goto return_results;
@ -179,7 +181,7 @@ bdb_attribute(
if( conn != NULL
&& op != NULL
&& access_allowed(be, conn, op, e, entry_at,
&attr->a_vals[i], ACL_READ) == 0)
&attr->a_vals[i], ACL_READ, &acl_state ) == 0)
{
continue;
}

View file

@ -169,7 +169,7 @@ bdb_bind(
}
if ( ! access_allowed( be, conn, op, e,
password, NULL, ACL_AUTH ) )
password, NULL, ACL_AUTH, NULL ) )
{
send_ldap_result( conn, op, rc = LDAP_INSUFFICIENT_ACCESS,
NULL, NULL, NULL, NULL );
@ -200,7 +200,7 @@ bdb_bind(
}
if ( ! access_allowed( be, conn, op, e,
krbattr, NULL, ACL_AUTH ) )
krbattr, NULL, ACL_AUTH, NULL ) )
{
send_ldap_result( conn, op, rc = LDAP_INSUFFICIENT_ACCESS,
NULL, NULL, NULL, NULL );

View file

@ -86,7 +86,7 @@ bdb_compare(
}
if ( ! access_allowed( be, conn, op, e,
ava->aa_desc, &ava->aa_value, ACL_COMPARE ) )
ava->aa_desc, &ava->aa_value, ACL_COMPARE, NULL ) )
{
rc = LDAP_INSUFFICIENT_ACCESS;
goto return_results;

View file

@ -120,7 +120,7 @@ retry: /* transaction retry */
/* check parent for "children" acl */
rc = access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE );
children, NULL, ACL_WRITE, NULL );
bdb_cache_return_entry_r(&bdb->bi_cache, p);
p = NULL;
@ -148,7 +148,7 @@ retry: /* transaction retry */
/* check parent for "children" acl */
rc = access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE );
children, NULL, ACL_WRITE, NULL );
p = NULL;
switch( opinfo.boi_err ) {

View file

@ -203,7 +203,7 @@ retry: /* transaction retry */
/* check parent for "children" acl */
if ( ! access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE ) )
children, NULL, ACL_WRITE, NULL ) )
{
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
0, 0 );
@ -237,7 +237,7 @@ retry: /* transaction retry */
/* check parent for "children" acl */
rc = access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE );
children, NULL, ACL_WRITE, NULL );
p = NULL;
@ -317,7 +317,7 @@ retry: /* transaction retry */
np, (long) np->e_id, 0 );
/* check newSuperior for "children" acl */
if ( !access_allowed( be, conn, op, np, children, NULL, ACL_WRITE ) ) {
if ( !access_allowed( be, conn, op, np, children, NULL, ACL_WRITE, NULL ) ) {
Debug( LDAP_DEBUG_TRACE,
"bdb_modrdn: no wr to newSup children\n",
0, 0, 0 );
@ -360,7 +360,7 @@ retry: /* transaction retry */
/* check parent for "children" acl */
rc = access_allowed( be, conn, op, np,
children, NULL, ACL_WRITE );
children, NULL, ACL_WRITE, NULL );
np = NULL;
@ -487,7 +487,7 @@ retry: /* transaction retry */
/* ACL check of newly added attrs */
if ( !access_allowed( be, conn, op, e, desc,
&new_rdn[0][ a_cnt ]->la_value, ACL_WRITE ) ) {
&new_rdn[0][ a_cnt ]->la_value, ACL_WRITE, NULL ) ) {
Debug( LDAP_DEBUG_TRACE,
"bdb_modrdn: access to attr \"%s\" "
"(new) not allowed\n",
@ -537,7 +537,7 @@ retry: /* transaction retry */
/* ACL check of newly added attrs */
if ( !access_allowed( be, conn, op, e, desc,
&old_rdn[0][d_cnt]->la_value, ACL_WRITE ) ) {
&old_rdn[0][d_cnt]->la_value, ACL_WRITE, NULL ) ) {
Debug( LDAP_DEBUG_TRACE,
"bdb_modrdn: access to attr \"%s\" "
"(old) not allowed\n",

View file

@ -126,7 +126,7 @@ ldbm_back_add(
}
if ( ! access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE ) )
children, NULL, ACL_WRITE, NULL ) )
{
/* free parent and writer lock */
cache_return_entry_w( &li->li_cache, p );
@ -207,7 +207,7 @@ ldbm_back_add(
p = (Entry *)&slap_entry_root;
rc = access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE );
children, NULL, ACL_WRITE, NULL );
p = NULL;
if ( ! rc ) {

View file

@ -37,6 +37,7 @@ ldbm_back_attribute(
BerVarray v;
const char *entry_at_name = entry_at->ad_cname.bv_val;
struct berval *iv, *jv;
AccessControlState acl_state = ACL_STATE_INIT;
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_ARGS,
@ -102,7 +103,7 @@ ldbm_back_attribute(
}
/* find attribute values */
if( is_entry_alias( e ) ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
@ -130,8 +131,8 @@ ldbm_back_attribute(
}
if (conn != NULL && op != NULL
&& access_allowed(be, conn, op, e, slap_schema.si_ad_entry,
NULL, ACL_READ) == 0)
&& access_allowed( be, conn, op, e, slap_schema.si_ad_entry,
NULL, ACL_READ, NULL ) == 0)
{
rc = LDAP_INSUFFICIENT_ACCESS;
goto return_results;
@ -152,7 +153,8 @@ ldbm_back_attribute(
}
if (conn != NULL && op != NULL
&& access_allowed(be, conn, op, e, entry_at, NULL, ACL_READ) == 0)
&& access_allowed( be, conn, op, e, entry_at, NULL,
ACL_READ, &acl_state ) == 0)
{
rc = LDAP_INSUFFICIENT_ACCESS;
goto return_results;
@ -167,8 +169,8 @@ ldbm_back_attribute(
for ( iv=attr->a_vals, jv=v; iv->bv_val; iv++ ) {
if( conn != NULL
&& op != NULL
&& access_allowed(be, conn, op, e, entry_at,
iv, ACL_READ) == 0)
&& access_allowed( be, conn, op, e, entry_at,
iv, ACL_READ, &acl_state ) == 0)
{
continue;
}

View file

@ -169,7 +169,7 @@ ldbm_back_bind(
}
if ( ! access_allowed( be, conn, op, e,
password, NULL, ACL_AUTH ) )
password, NULL, ACL_AUTH, NULL ) )
{
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
NULL, NULL, NULL, NULL );
@ -207,7 +207,7 @@ ldbm_back_bind(
}
if ( ! access_allowed( be, conn, op, e,
krbattr, NULL, ACL_AUTH ) )
krbattr, NULL, ACL_AUTH, NULL ) )
{
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
NULL, NULL, NULL, NULL );

View file

@ -87,7 +87,7 @@ ldbm_back_compare(
}
if ( ! access_allowed( be, conn, op, e,
ava->aa_desc, &ava->aa_value, ACL_COMPARE ) )
ava->aa_desc, &ava->aa_value, ACL_COMPARE, NULL ) )
{
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
NULL, NULL, NULL, NULL );
@ -107,7 +107,6 @@ ldbm_back_compare(
rc = LDAP_COMPARE_TRUE;
break;
}
}
send_ldap_result( conn, op, rc,

View file

@ -138,7 +138,7 @@ ldbm_back_delete(
/* check parent for "children" acl */
if ( ! access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE ) )
children, NULL, ACL_WRITE, NULL ) )
{
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
@ -162,7 +162,7 @@ ldbm_back_delete(
p = (Entry *)&slap_entry_root;
rc = access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE );
children, NULL, ACL_WRITE, NULL );
p = NULL;
/* check parent for "children" acl */

View file

@ -181,7 +181,7 @@ ldbm_back_modrdn(
/* check parent for "children" acl */
if ( ! access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE ) )
children, NULL, ACL_WRITE, NULL ) )
{
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
@ -228,7 +228,7 @@ ldbm_back_modrdn(
p = (Entry *)&slap_entry_root;
rc = access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE );
children, NULL, ACL_WRITE, NULL );
p = NULL;
/* check parent for "children" acl */
@ -342,7 +342,7 @@ ldbm_back_modrdn(
/* check newSuperior for "children" acl */
if ( !access_allowed( be, conn, op, np, children, NULL,
ACL_WRITE ) )
ACL_WRITE, NULL ) )
{
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
@ -403,7 +403,7 @@ ldbm_back_modrdn(
np = (Entry *)&slap_entry_root;
rc = access_allowed( be, conn, op, np,
children, NULL, ACL_WRITE );
children, NULL, ACL_WRITE, NULL );
np = NULL;
/* check parent for "children" acl */
@ -593,7 +593,7 @@ ldbm_back_modrdn(
}
if ( ! access_allowed( be, conn, op, e,
desc, &new_rdn[0][a_cnt]->la_value, ACL_WRITE ) ) {
desc, &new_rdn[0][a_cnt]->la_value, ACL_WRITE, NULL ) ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
"ldbm_back_modrdn: access "
@ -666,7 +666,7 @@ ldbm_back_modrdn(
}
if ( ! access_allowed( be, conn, op, e,
desc, &old_rdn[0][d_cnt]->la_value, ACL_WRITE ) ) {
desc, &old_rdn[0][d_cnt]->la_value, ACL_WRITE, NULL ) ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
"ldbm_back_modrdn: access "

View file

@ -291,7 +291,7 @@ static int compare_entry(
Attribute *a;
if ( ! access_allowed( NULL, conn, op, e,
ava->aa_desc, &ava->aa_value, ACL_COMPARE ) )
ava->aa_desc, &ava->aa_value, ACL_COMPARE, NULL ) )
{
return LDAP_INSUFFICIENT_ACCESS;
}

View file

@ -1963,7 +1963,7 @@ read_config( const char *fname )
}
/* file from which to read additional rootdse attrs */
} else if ( strcasecmp( cargv[0], "rootdse" ) == 0) {
} else if ( strcasecmp( cargv[0], "rootDSE" ) == 0) {
if ( cargc < 2 ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: "

View file

@ -228,7 +228,7 @@ static int test_mra_filter(
Attribute *a;
if( !access_allowed( be, conn, op, e,
mra->ma_desc, &mra->ma_value, ACL_SEARCH ) )
mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) )
{
return LDAP_INSUFFICIENT_ACCESS;
}
@ -285,7 +285,7 @@ test_ava_filter(
Attribute *a;
if ( !access_allowed( be, conn, op, e,
ava->aa_desc, &ava->aa_value, ACL_SEARCH ) )
ava->aa_desc, &ava->aa_value, ACL_SEARCH, NULL ) )
{
return LDAP_INSUFFICIENT_ACCESS;
}
@ -370,7 +370,7 @@ test_presence_filter(
AttributeDescription *desc
)
{
if ( !access_allowed( be, conn, op, e, desc, NULL, ACL_SEARCH ) )
if ( !access_allowed( be, conn, op, e, desc, NULL, ACL_SEARCH, NULL ) )
{
return LDAP_INSUFFICIENT_ACCESS;
}
@ -491,7 +491,7 @@ test_substrings_filter(
if ( !access_allowed( be, conn, op, e,
f->f_sub_desc, NULL, ACL_SEARCH ) )
f->f_sub_desc, NULL, ACL_SEARCH, NULL ) )
{
return LDAP_INSUFFICIENT_ACCESS;
}

View file

@ -16,7 +16,8 @@ LDAP_BEGIN_DECL
LDAP_SLAPD_F (int) access_allowed LDAP_P((
Backend *be, Connection *conn, Operation *op,
Entry *e, AttributeDescription *desc, struct berval *val,
slap_access_t access ));
slap_access_t access,
AccessControlState *state ));
LDAP_SLAPD_F (int) acl_check_modlist LDAP_P((
Backend *be, Connection *conn, Operation *op,
Entry *e, Modifications *ml ));

View file

@ -628,6 +628,8 @@ send_search_entry(
char *edn;
int userattrs;
int opattrs;
static AccessControlState acl_state_init = ACL_STATE_INIT;
AccessControlState acl_state;
AttributeDescription *ad_entry = slap_schema.si_ad_entry;
@ -647,9 +649,8 @@ send_search_entry(
e->e_dn, attrsonly ? " (attrsOnly)" : "", 0 );
#endif
if ( ! access_allowed( be, conn, op, e,
ad_entry, NULL, ACL_READ ) )
ad_entry, NULL, ACL_READ, NULL ) )
{
#ifdef NEW_LOGGING
LDAP_LOG(( "acl", LDAP_LEVEL_INFO,
@ -739,7 +740,11 @@ send_search_entry(
}
}
if ( ! access_allowed( be, conn, op, e, desc, NULL, ACL_READ ) ) {
acl_state = acl_state_init;
if ( ! access_allowed( be, conn, op, e, desc, NULL,
ACL_READ, &acl_state ) )
{
#ifdef NEW_LOGGING
LDAP_LOG(( "acl", LDAP_LEVEL_INFO, "send_search_entry: "
"conn %d access to attribute %s not allowed\n",
@ -749,7 +754,6 @@ send_search_entry(
"access to attribute %s not allowed\n",
desc->ad_cname.bv_val, 0, 0 );
#endif
continue;
}
@ -771,12 +775,13 @@ send_search_entry(
if ( ! attrsonly ) {
for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
if ( ! access_allowed( be, conn, op, e,
desc, &a->a_vals[i], ACL_READ ) )
desc, &a->a_vals[i], ACL_READ, &acl_state ) )
{
#ifdef NEW_LOGGING
LDAP_LOG(( "acl", LDAP_LEVEL_INFO,
"send_search_entry: conn %d access to attribute %s, value %d not allowed\n",
op->o_connid, desc->ad_cname.bv_val, i ));
"send_search_entry: conn %d "
"access to attribute %s, value %d not allowed\n",
op->o_connid, desc->ad_cname.bv_val, i ));
#else
Debug( LDAP_DEBUG_ACL,
"acl: access to attribute %s, value %d not allowed\n",
@ -789,8 +794,8 @@ send_search_entry(
if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
"send_search_entry: conn %d ber_printf failed.\n",
op->o_connid ));
"send_search_entry: conn %d ber_printf failed.\n",
op->o_connid ));
#else
Debug( LDAP_DEBUG_ANY,
"ber_printf failed\n", 0, 0, 0 );
@ -807,8 +812,8 @@ send_search_entry(
if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
"send_search_entry: conn %d ber_printf failed\n",
op->o_connid ));
"send_search_entry: conn %d ber_printf failed\n",
op->o_connid ));
#else
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
#endif
@ -847,11 +852,16 @@ send_search_entry(
}
}
if ( ! access_allowed( be, conn, op, e, desc, NULL, ACL_READ ) ) {
acl_state = acl_state_init;
if ( ! access_allowed( be, conn, op, e, desc, NULL,
ACL_READ, &acl_state ) )
{
#ifdef NEW_LOGGING
LDAP_LOG(( "acl", LDAP_LEVEL_INFO,
"send_search_entry: conn %s access to attribute %s not allowed\n",
op->o_connid, desc->ad_cname.bv_val ));
"send_search_entry: conn %s "
"access to attribute %s not allowed\n",
op->o_connid, desc->ad_cname.bv_val ));
#else
Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s not allowed\n",
desc->ad_cname.bv_val, 0, 0 );
@ -864,8 +874,8 @@ send_search_entry(
if ( rc == -1 ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
"send_search_entry: conn %d ber_printf failed\n",
op->o_connid ));
"send_search_entry: conn %d ber_printf failed\n",
op->o_connid ));
#else
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
#endif
@ -880,12 +890,13 @@ send_search_entry(
if ( ! attrsonly ) {
for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
if ( ! access_allowed( be, conn, op, e,
desc, &a->a_vals[i], ACL_READ ) )
desc, &a->a_vals[i], ACL_READ, &acl_state ) )
{
#ifdef NEW_LOGGING
LDAP_LOG(( "acl", LDAP_LEVEL_INFO,
"send_search_entry: conn %d access to %s, value %d not allowed\n",
op->o_connid, desc->ad_cname.bv_val, i ));
"send_search_entry: conn %d "
"access to %s, value %d not allowed\n",
op->o_connid, desc->ad_cname.bv_val, i ));
#else
Debug( LDAP_DEBUG_ACL,
"acl: access to attribute %s, value %d not allowed\n",
@ -895,7 +906,6 @@ send_search_entry(
continue;
}
if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
@ -989,7 +999,6 @@ send_search_entry(
Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
#endif
rc = 0;
error_return:;
@ -1027,7 +1036,7 @@ send_search_reference(
if ( ! access_allowed( be, conn, op, e,
ad_entry, NULL, ACL_READ ) )
ad_entry, NULL, ACL_READ, NULL ) )
{
#ifdef NEW_LOGGING
LDAP_LOG(( "acl", LDAP_LEVEL_INFO,
@ -1043,7 +1052,7 @@ send_search_reference(
}
if ( ! access_allowed( be, conn, op, e,
ad_ref, NULL, ACL_READ ) )
ad_ref, NULL, ACL_READ, NULL ) )
{
#ifdef NEW_LOGGING
LDAP_LOG(( "acl", LDAP_LEVEL_INFO,

View file

@ -948,6 +948,26 @@ typedef struct slap_acl {
struct slap_acl *acl_next;
} AccessControl;
typedef struct slap_acl_state {
unsigned as_recorded;
#define ACL_STATE_NOT_RECORDED 0x0
#define ACL_STATE_RECORDED_VD 0x1
#define ACL_STATE_RECORDED_NV 0x2
#define ACL_STATE_RECORDED 0x3
/* Access state */
AccessControl *as_vd_acl;
slap_mask_t as_vd_acl_mask;
regmatch_t as_vd_acl_matches[MAXREMATCHES];
int as_vd_acl_count;
Access *as_vd_access;
int as_vd_access_count;
int as_result;
} AccessControlState;
#define ACL_STATE_INIT { ACL_STATE_NOT_RECORDED, NULL, 0UL, { 0 }, 0, NULL, 0 }
/*
* replog moddn param structure
*/
@ -1138,7 +1158,6 @@ struct slap_backend_db {
struct berval be_update_ndn; /* allowed to make changes (in replicas) */
BerVarray be_update_refs; /* where to refer modifying clients to */
char *be_realm;
void *be_private; /* anything the backend database needs */
};