/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2008 The OpenLDAP Foundation.
+ * Copyright 1998-2009 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
AttributeDescription *desc,
struct berval *val,
AclRegexMatches *matches,
+ slap_mask_t *mask,
AccessControlState *state );
static slap_control_t slap_acl_mask(
slap_access_t access );
static int regex_matches(
- struct berval *pat, char *str, char *buf,
+ struct berval *pat, char *str,
+ struct berval *dn_matches, struct berval *val_matches,
AclRegexMatches *matches);
typedef struct AclSetCookie {
const char *attr;
AclRegexMatches matches;
AccessControlState acl_state = ACL_STATE_INIT;
+ static AccessControlState state_init = ACL_STATE_INIT;
assert( op != NULL );
assert( e != NULL );
if ( state == NULL )
state = &acl_state;
- if ( state->as_vd_ad == desc ) {
+ if ( state->as_desc == desc &&
+ state->as_access == access &&
+ state->as_vd_acl != NULL )
+ {
a = state->as_vd_acl;
count = state->as_vd_acl_count;
if ( state->as_fe_done )
state->as_fe_done--;
+ ACL_PRIV_ASSIGN( mask, state->as_vd_mask );
} else {
- state->as_vi_acl = NULL;
+ *state = state_init;
a = NULL;
count = 0;
+ ACL_PRIV_ASSIGN( mask, *maskp );
}
- if ( a == NULL )
- state->as_fe_done = 0;
- ACL_PRIV_ASSIGN( mask, *maskp );
MATCHES_MEMSET( &matches );
while ( ( a = slap_acl_get( a, &count, op, e, desc, val,
- &matches, state ) ) != NULL )
+ &matches, &mask, state ) ) != NULL )
{
int i;
int dnmaxcount = MATCHES_DNMAXCOUNT( &matches );
/* DN matches */
for ( i = 0; i < dnmaxcount && dn_data[i].rm_eo > 0; i++ ) {
- char *debugmsg = "=> match[dn%d]: %d %d ";
char *data = e->e_ndn;
- Debug( LDAP_DEBUG_ACL, debugmsg, i,
+ Debug( LDAP_DEBUG_ACL, "=> match[dn%d]: %d %d ", i,
(int)dn_data[i].rm_so,
(int)dn_data[i].rm_eo );
if ( dn_data[i].rm_so <= dn_data[0].rm_eo ) {
/* val matches */
for ( i = 0; i < valmaxcount && val_data[i].rm_eo > 0; i++ ) {
- char *debugmsg = "=> match[val%d]: %d %d ";
char *data = val->bv_val;
- Debug( LDAP_DEBUG_ACL, debugmsg, i,
+ Debug( LDAP_DEBUG_ACL, "=> match[val%d]: %d %d ", i,
(int)val_data[i].rm_so,
(int)val_data[i].rm_eo );
if ( val_data[i].rm_so <= val_data[0].rm_eo ) {
Debug( LDAP_DEBUG_ACL, "\n", 0, 0, 0 );
}
- if ( state ) {
- if ( state->as_vi_acl == a &&
- ( state->as_recorded & ACL_STATE_RECORDED_NV ) )
- {
- Debug( LDAP_DEBUG_ACL,
- "=> slap_access_allowed: result was in cache (%s)\n",
- attr, 0, 0 );
- ret = state->as_result;
- goto done;
- } else {
- Debug( LDAP_DEBUG_ACL,
- "=> slap_access_allowed: result not in cache (%s)\n",
- attr, 0, 0 );
- }
- }
-
control = slap_acl_mask( a, &mask, op,
e, desc, val, &matches, count, state, access );
slap_mask_t *maskp )
{
int ret = 1;
- AccessControl *a = NULL;
int be_null = 0;
#ifdef LDAP_DEBUG
slap_mask_t mask;
slap_access_t access_level;
const char *attr;
- static AccessControlState state_init = ACL_STATE_INIT;
assert( e != NULL );
assert( desc != NULL );
}
}
- if ( state ) {
- if ( state->as_vd_ad == desc ) {
- if ( ( state->as_recorded & ACL_STATE_RECORDED_NV ) &&
- val == NULL )
+ if ( state != NULL ) {
+ if ( state->as_desc == desc &&
+ state->as_access == access &&
+ state->as_result != -1 &&
+ state->as_vd_acl == NULL )
{
+ Debug( LDAP_DEBUG_ACL,
+ "=> access_allowed: result was in cache (%s)\n",
+ attr, 0, 0 );
return state->as_result;
-
- }
} else {
- *state = state_init;
+ Debug( LDAP_DEBUG_ACL,
+ "=> access_allowed: result not in cache (%s)\n",
+ attr, 0, 0 );
}
}
done:
if ( state != NULL ) {
- /* If not value-dependent, save ACL in case of more attrs */
- if ( !( state->as_recorded & ACL_STATE_RECORDED_VD ) ) {
- state->as_vi_acl = a;
+ state->as_access = access;
state->as_result = ret;
- }
- state->as_recorded |= ACL_STATE_RECORDED;
- state->as_vd_ad = desc;
+ state->as_desc = desc;
}
if ( be_null ) op->o_bd = NULL;
if ( maskp ) ACL_PRIV_ASSIGN( *maskp, mask );
AttributeDescription *desc,
struct berval *val,
AclRegexMatches *matches,
+ slap_mask_t *mask,
AccessControlState *state )
{
const char *attr;
- int dnlen, patlen;
+ ber_len_t dnlen;
AccessControl *prev;
assert( e != NULL );
continue;
} else {
+ ber_len_t patlen;
+
Debug( LDAP_DEBUG_ACL, "=> dn: [%d] %s\n",
*count, a->acl_dn_pat.bv_val, 0 );
patlen = a->acl_dn_pat.bv_len;
} else if ( a->acl_dn_style == ACL_STYLE_ONE ) {
ber_len_t rdnlen = 0;
- int sep = 0;
+ ber_len_t sep = 0;
if ( dnlen <= patlen )
continue;
}
rdnlen = dn_rdnlen( NULL, &e->e_nname );
- if ( rdnlen != dnlen - patlen - sep )
+ if ( rdnlen + patlen + sep != dnlen )
continue;
} else if ( a->acl_dn_style == ACL_STYLE_SUBTREE ) {
continue;
}
- if( !( state->as_recorded & ACL_STATE_RECORDED_VD )) {
- state->as_recorded |= ACL_STATE_RECORDED_VD;
+ if ( state->as_vd_acl == NULL ) {
state->as_vd_acl = prev;
state->as_vd_acl_count = *count - 1;
+ ACL_PRIV_ASSIGN ( state->as_vd_mask, *mask );
}
if ( a->acl_attrval_style == ACL_STYLE_REGEX ) {
- int rc;
-
Debug( LDAP_DEBUG_ACL,
"acl_get: valpat %s\n",
a->acl_attrval.bv_val, 0, 0 );
- if ( rc = regexec ( &a->acl_attrval_re,
+ if ( regexec ( &a->acl_attrval_re,
val->bv_val,
matches->val_count,
matches->val_data, 0 ) )
continue;
} else {
- int patlen, vdnlen;
+ ber_len_t patlen, vdnlen;
patlen = a->acl_attrval.bv_len;
vdnlen = val->bv_len;
continue;
rdnlen = dn_rdnlen( NULL, val );
- if ( rdnlen != vdnlen - patlen - 1 )
+ if ( rdnlen + patlen + 1 != vdnlen )
continue;
} else if ( a->acl_attrval_style == ACL_STYLE_SUBTREE ) {
* 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; \
+ if( state && state->as_vd_acl == NULL ) { \
state->as_vd_acl = a; \
state->as_vd_acl_count = count; \
+ ACL_PRIV_ASSIGN( state->as_vd_mask, *mask ); \
} \
} while( 0 )
acl_mask_dn(
Operation *op,
Entry *e,
- AttributeDescription *desc,
struct berval *val,
AccessControl *a,
AclRegexMatches *matches,
AclRegexMatches tmp_matches,
*tmp_matchesp = &tmp_matches;
int rc = 0;
- int dnoffset;
regmatch_t *tmp_data;
MATCHES_MEMSET( &tmp_matches );
}
if ( !regex_matches( &bdn->a_pat, opndn->bv_val,
- e->e_ndn, tmp_matchesp ) )
+ &e->e_nname, NULL, tmp_matchesp ) )
{
return 1;
}
}
if ( acl_string_expand( &bv, &bdn->a_pat,
- e->e_nname.bv_val,
- val->bv_val, tmp_matchesp ) )
+ &e->e_nname,
+ val, tmp_matchesp ) )
{
return 1;
}
Entry *e,
struct berval *val,
AccessControl *a,
- Access *b,
- int i,
- AclRegexMatches *matches,
int count,
AccessControlState *state,
+ slap_mask_t *mask,
slap_dn_access *bdn,
struct berval *opndn )
{
char accessmaskbuf[ACCESSMASK_MAXLEN];
#endif /* DEBUG */
const char *attr;
+#ifdef SLAP_DYNACL
slap_mask_t a2pmask = ACL_ACCESS2PRIV( access );
+#endif /* SLAP_DYNACL */
assert( a != NULL );
assert( mask != NULL );
* is maintained in a_dn_pat.
*/
- if ( acl_mask_dn( op, e, desc, val, a, matches,
+ if ( acl_mask_dn( op, e, val, a, matches,
&b->a_dn, &op->o_ndn ) )
{
continue;
ndn = op->o_ndn;
}
- if ( acl_mask_dn( op, e, desc, val, a, matches,
+ if ( acl_mask_dn( op, e, val, a, matches,
&b->a_realdn, &ndn ) )
{
continue;
if ( !ber_bvccmp( &b->a_sockurl_pat, '*' ) ) {
if ( b->a_sockurl_style == ACL_STYLE_REGEX) {
- if (!regex_matches( &b->a_sockurl_pat, op->o_conn->c_listener_url.bv_val,
- e->e_ndn, matches ) )
+ if ( !regex_matches( &b->a_sockurl_pat, op->o_conn->c_listener_url.bv_val,
+ &e->e_nname, val, matches ) )
{
continue;
}
bv.bv_len = sizeof( buf ) - 1;
bv.bv_val = buf;
- if ( acl_string_expand( &bv, &b->a_sockurl_pat, e->e_ndn, val->bv_val, matches ) )
+ if ( acl_string_expand( &bv, &b->a_sockurl_pat, &e->e_nname, val, matches ) )
{
continue;
}
b->a_domain_pat.bv_val, 0, 0 );
if ( !ber_bvccmp( &b->a_domain_pat, '*' ) ) {
if ( b->a_domain_style == ACL_STYLE_REGEX) {
- if (!regex_matches( &b->a_domain_pat, op->o_conn->c_peer_domain.bv_val,
- e->e_ndn, matches ) )
+ if ( !regex_matches( &b->a_domain_pat, op->o_conn->c_peer_domain.bv_val,
+ &e->e_nname, val, matches ) )
{
continue;
}
bv.bv_len = sizeof(buf) - 1;
bv.bv_val = buf;
- if ( acl_string_expand(&bv, &b->a_domain_pat, e->e_ndn, val->bv_val, matches) )
+ if ( acl_string_expand(&bv, &b->a_domain_pat, &e->e_nname, val, matches) )
{
continue;
}
b->a_peername_pat.bv_val, 0, 0 );
if ( !ber_bvccmp( &b->a_peername_pat, '*' ) ) {
if ( b->a_peername_style == ACL_STYLE_REGEX ) {
- if (!regex_matches( &b->a_peername_pat, op->o_conn->c_peer_name.bv_val,
- e->e_ndn, matches ) )
+ if ( !regex_matches( &b->a_peername_pat, op->o_conn->c_peer_name.bv_val,
+ &e->e_nname, val, matches ) )
{
continue;
}
bv.bv_len = sizeof( buf ) - 1;
bv.bv_val = buf;
- if ( acl_string_expand( &bv, &b->a_peername_pat, e->e_ndn, val->bv_val, matches ) )
+ if ( acl_string_expand( &bv, &b->a_peername_pat, &e->e_nname, val, matches ) )
{
continue;
}
b->a_sockname_pat.bv_val, 0, 0 );
if ( !ber_bvccmp( &b->a_sockname_pat, '*' ) ) {
if ( b->a_sockname_style == ACL_STYLE_REGEX) {
- if (!regex_matches( &b->a_sockname_pat, op->o_conn->c_sock_name.bv_val,
- e->e_ndn, matches ) )
+ if ( !regex_matches( &b->a_sockname_pat, op->o_conn->c_sock_name.bv_val,
+ &e->e_nname, val, matches ) )
{
continue;
}
bv.bv_len = sizeof( buf ) - 1;
bv.bv_val = buf;
- if ( acl_string_expand( &bv, &b->a_sockname_pat, e->e_ndn, val->bv_val, matches ) )
+ if ( acl_string_expand( &bv, &b->a_sockname_pat, &e->e_nname, val, matches ) )
{
continue;
}
}
if ( b->a_dn_at != NULL ) {
- if ( acl_mask_dnattr( op, e, val, a, b, i,
- matches, count, state,
+ if ( acl_mask_dnattr( op, e, val, a,
+ count, state, mask,
&b->a_dn, &op->o_ndn ) )
{
continue;
ndn = op->o_ndn;
}
- if ( acl_mask_dnattr( op, e, val, a, b, i,
- matches, count, state,
+ if ( acl_mask_dnattr( op, e, val, a,
+ count, state, mask,
&b->a_realdn, &ndn ) )
{
continue;
}
if ( acl_string_expand( &bv, &b->a_group_pat,
- e->e_nname.bv_val, val->bv_val,
+ &e->e_nname, val,
tmp_matchesp ) )
{
continue;
}
if ( acl_string_expand( &bv, &b->a_set_pat,
- e->e_nname.bv_val, val->bv_val,
+ &e->e_nname, val,
tmp_matchesp ) )
{
continue;
if ( ! access_allowed( op, e,
mlist->sml_desc, NULL,
( mlist->sml_flags & SLAP_MOD_MANAGING ) ? ACL_MANAGE : ACL_WDEL,
- NULL ) )
+ &state ) )
{
ret = 0;
goto done;
acl_string_expand(
struct berval *bv,
struct berval *pat,
- char *dn_match,
- char *val_match,
+ struct berval *dn_matches,
+ struct berval *val_matches,
AclRegexMatches *matches)
{
ber_len_t size;
case DN_FLAG:
nm = matches->dn_count;
m = matches->dn_data;
- data = dn_match;
+ data = dn_matches ? dn_matches->bv_val : NULL;
break;
case VAL_FLAG:
nm = matches->val_count;
m = matches->val_data;
- data = val_match;
+ data = val_matches ? val_matches->bv_val : NULL;
break;
+ default:
+ assert( 0 );
}
if ( n >= nm ) {
/* FIXME: error */
regex_matches(
struct berval *pat, /* pattern to expand and match against */
char *str, /* string to match against pattern */
- char *buf, /* buffer with $N expansion variables */
+ struct berval *dn_matches, /* buffer with $N expansion variables from DN */
+ struct berval *val_matches, /* buffer with $N expansion variables from val */
AclRegexMatches *matches /* offsets in buffer for $N expansion variables */
)
{
str = "";
};
- acl_string_expand( &bv, pat, buf, NULL, matches );
+ acl_string_expand( &bv, pat, dn_matches, val_matches, matches );
rc = regcomp( &re, newbuf, REG_EXTENDED|REG_ICASE );
if ( rc ) {
char error[ACL_BUF_SIZE];