/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2006 The OpenLDAP Foundation.
+ * Copyright 1998-2009 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#define ACL_BUF_SIZE 1024 /* use most appropriate size */
static const struct berval acl_bv_ip_eq = BER_BVC( "IP=" );
+#ifdef LDAP_PF_INET6
+static const struct berval acl_bv_ipv6_eq = BER_BVC( "IP=[" );
+#endif /* LDAP_PF_INET6 */
#ifdef LDAP_PF_LOCAL
static const struct berval acl_bv_path_eq = BER_BVC("PATH=");
#endif /* LDAP_PF_LOCAL */
Operation *op, Entry *e,
AttributeDescription *desc,
struct berval *val,
- int nmatch, regmatch_t *matches,
+ AclRegexMatches *matches,
+ slap_mask_t *mask,
AccessControlState *state );
static slap_control_t slap_acl_mask(
Operation *op, Entry *e,
AttributeDescription *desc,
struct berval *val,
- int nmatch,
- regmatch_t *matches,
+ AclRegexMatches *matches,
int count,
- AccessControlState *state );
+ AccessControlState *state,
+ slap_access_t access );
static int regex_matches(
- struct berval *pat, char *str, char *buf,
- int nmatch, regmatch_t *matches);
+ struct berval *pat, char *str,
+ struct berval *dn_matches, struct berval *val_matches,
+ AclRegexMatches *matches);
typedef struct AclSetCookie {
SetCookie asc_cookie;
Entry *asc_e;
} AclSetCookie;
+
SLAP_SET_GATHER acl_set_gather;
SLAP_SET_GATHER acl_set_gather2;
return 1;
}
+#define MATCHES_DNMAXCOUNT(m) \
+ ( sizeof ( (m)->dn_data ) / sizeof( *(m)->dn_data ) )
+#define MATCHES_VALMAXCOUNT(m) \
+ ( sizeof ( (m)->val_data ) / sizeof( *(m)->val_data ) )
+#define MATCHES_MEMSET(m) do { \
+ memset( (m)->dn_data, '\0', sizeof( (m)->dn_data ) ); \
+ memset( (m)->val_data, '\0', sizeof( (m)->val_data ) ); \
+ (m)->dn_count = MATCHES_DNMAXCOUNT( (m) ); \
+ (m)->val_count = MATCHES_VALMAXCOUNT( (m) ); \
+} while ( 0 /* CONSTCOND */ )
+
int
slap_access_allowed(
Operation *op,
slap_control_t control;
slap_access_t access_level;
const char *attr;
- regmatch_t matches[MAXREMATCHES];
+ AclRegexMatches matches;
+ AccessControlState acl_state = ACL_STATE_INIT;
+ static AccessControlState state_init = ACL_STATE_INIT;
assert( op != NULL );
assert( e != NULL );
}
/* use backend default access if no backend acls */
- if ( op->o_bd->be_acl == NULL ) {
+ if ( op->o_bd->be_acl == NULL && frontendDB->be_acl == NULL ) {
int i;
Debug( LDAP_DEBUG_ACL,
ret = 0;
control = ACL_BREAK;
- if ( state && state->as_vd_ad == desc ) {
+ if ( state == NULL )
+ state = &acl_state;
+ 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 {
- if ( state ) state->as_vi_acl = NULL;
+ *state = state_init;
+
a = NULL;
count = 0;
+ ACL_PRIV_ASSIGN( mask, *maskp );
}
- ACL_PRIV_ASSIGN( mask, *maskp );
- memset( matches, '\0', sizeof( matches ) );
+
+ MATCHES_MEMSET( &matches );
while ( ( a = slap_acl_get( a, &count, op, e, desc, val,
- MAXREMATCHES, matches, state ) ) != NULL )
+ &matches, &mask, state ) ) != NULL )
{
- int i;
-
- for ( i = 0; i < MAXREMATCHES && matches[i].rm_so > 0; i++ ) {
- Debug( LDAP_DEBUG_ACL, "=> match[%d]: %d %d ", i,
- (int)matches[i].rm_so, (int)matches[i].rm_eo );
- if ( matches[i].rm_so <= matches[0].rm_eo ) {
+ int i;
+ int dnmaxcount = MATCHES_DNMAXCOUNT( &matches );
+ int valmaxcount = MATCHES_VALMAXCOUNT( &matches );
+ regmatch_t *dn_data = matches.dn_data;
+ regmatch_t *val_data = matches.val_data;
+
+ /* DN matches */
+ for ( i = 0; i < dnmaxcount && dn_data[i].rm_eo > 0; i++ ) {
+ char *data = e->e_ndn;
+
+ 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 ) {
int n;
- for ( n = matches[i].rm_so; n < matches[i].rm_eo; n++ ) {
- Debug( LDAP_DEBUG_ACL, "%c", e->e_ndn[n], 0, 0 );
+ for ( n = dn_data[i].rm_so;
+ n < dn_data[i].rm_eo; n++ ) {
+ Debug( LDAP_DEBUG_ACL, "%c",
+ data[n], 0, 0 );
}
}
- Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );
+ 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 from state (%s)\n",
- attr, 0, 0 );
- ret = state->as_result;
- goto done;
- } else {
- Debug( LDAP_DEBUG_ACL,
- "=> slap_access_allowed: no res from state (%s)\n",
- attr, 0, 0 );
+ /* val matches */
+ for ( i = 0; i < valmaxcount && val_data[i].rm_eo > 0; i++ ) {
+ char *data = val->bv_val;
+
+ 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 ) {
+ int n;
+ for ( n = val_data[i].rm_so;
+ n < val_data[i].rm_eo; n++ ) {
+ Debug( LDAP_DEBUG_ACL, "%c",
+ data[n], 0, 0 );
+ }
}
+ Debug( LDAP_DEBUG_ACL, "\n", 0, 0, 0 );
}
-vd_access:
control = slap_acl_mask( a, &mask, op,
- e, desc, val, MAXREMATCHES, matches, count, state );
+ e, desc, val, &matches, count, state, access );
if ( control != ACL_BREAK ) {
break;
}
- memset( matches, '\0', sizeof( matches ) );
+ MATCHES_MEMSET( &matches );
}
if ( ACL_IS_INVALID( mask ) ) {
be_orig = op->o_bd;
if ( op->o_bd == NULL ) {
- op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
+ op->o_bd = select_backend( &op->o_req_ndn, 0 );
if ( op->o_bd == NULL )
op->o_bd = frontendDB;
}
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 );
assert( attr != NULL );
if ( op ) {
- if ( op->o_is_auth_check &&
+ if ( op->o_acl_priv != ACL_NONE ) {
+ access = op->o_acl_priv;
+
+ } else if ( op->o_is_auth_check &&
( access_level == ACL_SEARCH || access_level == ACL_READ ) )
{
access = ACL_AUTH;
- } else if ( get_manageDIT( op ) && access_level == ACL_WRITE &&
+ } else if ( get_relax( op ) && access_level == ACL_WRITE &&
desc == slap_schema.si_ad_entry )
{
access = ACL_MANAGE;
}
}
- 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 );
}
}
op->o_bd = LDAP_STAILQ_FIRST( &backendDB );
be_null = 1;
-#ifdef LDAP_DEVEL
- /*
- * FIXME: experimental; use first backend rules
- * iff there is no global_acl (ITS#3100) */
+ /* FIXME: experimental; use first backend rules
+ * iff there is no global_acl (ITS#3100)
+ */
if ( frontendDB->be_acl != NULL ) {
op->o_bd = frontendDB;
}
-#endif /* LDAP_DEVEL */
}
assert( op->o_bd != NULL );
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 );
Entry *e,
AttributeDescription *desc,
struct berval *val,
- int nmatch,
- regmatch_t *matches,
+ AclRegexMatches *matches,
+ slap_mask_t *mask,
AccessControlState *state )
{
const char *attr;
- int dnlen, patlen;
+ ber_len_t dnlen;
AccessControl *prev;
assert( e != NULL );
assert( count != NULL );
assert( desc != NULL );
+ assert( state != NULL );
attr = desc->ad_cname.bv_val;
assert( attr != NULL );
if( a == NULL ) {
- if( op->o_bd == NULL ) {
+ if( op->o_bd == NULL || op->o_bd->be_acl == NULL ) {
a = frontendDB->be_acl;
} else {
a = op->o_bd->be_acl;
prev = NULL;
assert( a != NULL );
-
+ if ( a == frontendDB->be_acl )
+ state->as_fe_done = 1;
} else {
prev = a;
a = a->acl_next;
dnlen = e->e_nname.bv_len;
+ retry:
for ( ; a != NULL; prev = a, a = a->acl_next ) {
(*count) ++;
+ if ( a != frontendDB->be_acl && state->as_fe_done )
+ state->as_fe_done++;
+
if ( a->acl_dn_pat.bv_len || ( a->acl_dn_style != ACL_STYLE_REGEX )) {
if ( a->acl_dn_style == ACL_STYLE_REGEX ) {
Debug( LDAP_DEBUG_ACL, "=> dnpat: [%d] %s nsub: %d\n",
*count, a->acl_dn_pat.bv_val, (int) a->acl_dn_re.re_nsub );
- if (regexec(&a->acl_dn_re, e->e_ndn, nmatch, matches, 0))
+ if ( regexec ( &a->acl_dn_re,
+ e->e_ndn,
+ matches->dn_count,
+ matches->dn_data, 0 ) )
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 ) {
}
if ( a->acl_attrs && !ad_inlist( desc, a->acl_attrs ) ) {
- matches[0].rm_so = matches[0].rm_eo = -1;
+ matches->dn_data[0].rm_so = -1;
+ matches->dn_data[0].rm_eo = -1;
+ matches->val_data[0].rm_so = -1;
+ matches->val_data[0].rm_eo = -1;
continue;
}
continue;
}
- if( state && !( 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 ) {
Debug( LDAP_DEBUG_ACL,
"acl_get: valpat %s\n",
a->acl_attrval.bv_val, 0, 0 );
- if ( regexec( &a->acl_attrval_re, val->bv_val, 0, NULL, 0 ) )
+ if ( regexec ( &a->acl_attrval_re,
+ val->bv_val,
+ matches->val_count,
+ matches->val_data, 0 ) )
{
continue;
}
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 ) {
return a;
}
+ if ( !state->as_fe_done ) {
+ state->as_fe_done = 1;
+ a = frontendDB->be_acl;
+ goto retry;
+ }
+
Debug( LDAP_DEBUG_ACL, "<= acl_get: done.\n", 0, 0, 0 );
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; \
+ 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,
- int nmatch,
- regmatch_t *matches,
+ AclRegexMatches *matches,
slap_dn_access *bdn,
struct berval *opndn )
{
} else if ( bdn->a_style == ACL_STYLE_REGEX ) {
if ( !ber_bvccmp( &bdn->a_pat, '*' ) ) {
- int tmp_nmatch;
- regmatch_t tmp_matches[2],
- *tmp_matchesp = tmp_matches;
-
+ AclRegexMatches tmp_matches,
+ *tmp_matchesp = &tmp_matches;
int rc = 0;
+ regmatch_t *tmp_data;
- switch ( a->acl_dn_style ) {
+ MATCHES_MEMSET( &tmp_matches );
+ tmp_data = &tmp_matches.dn_data[0];
+
+ if ( a->acl_attrval_style == ACL_STYLE_REGEX )
+ tmp_matchesp = matches;
+ else switch ( a->acl_dn_style ) {
case ACL_STYLE_REGEX:
if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
- tmp_matchesp = matches;
- tmp_nmatch = nmatch;
+ tmp_matchesp = matches;
break;
}
/* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */
case ACL_STYLE_BASE:
- tmp_matches[0].rm_so = 0;
- tmp_matches[0].rm_eo = e->e_nname.bv_len;
- tmp_nmatch = 1;
+ tmp_data[0].rm_so = 0;
+ tmp_data[0].rm_eo = e->e_nname.bv_len;
+ tmp_matches.dn_count = 1;
break;
case ACL_STYLE_ONE:
case ACL_STYLE_SUBTREE:
case ACL_STYLE_CHILDREN:
- tmp_matches[0].rm_so = 0;
- tmp_matches[0].rm_eo = e->e_nname.bv_len;
- tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
- tmp_matches[1].rm_eo = e->e_nname.bv_len;
- tmp_nmatch = 2;
+ tmp_data[0].rm_so = 0;
+ tmp_data[0].rm_eo = e->e_nname.bv_len;
+ tmp_data[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
+ tmp_data[1].rm_eo = e->e_nname.bv_len;
+ tmp_matches.dn_count = 2;
break;
default:
}
if ( !regex_matches( &bdn->a_pat, opndn->bv_val,
- e->e_ndn, tmp_nmatch, tmp_matchesp ) )
+ &e->e_nname, NULL, tmp_matchesp ) )
{
return 1;
}
struct berval bv;
char buf[ACL_BUF_SIZE];
- int tmp_nmatch;
- regmatch_t tmp_matches[2],
- *tmp_matchesp = tmp_matches;
-
+ AclRegexMatches tmp_matches,
+ *tmp_matchesp = &tmp_matches;
int rc = 0;
+ regmatch_t *tmp_data;
+
+ MATCHES_MEMSET( &tmp_matches );
+ tmp_data = &tmp_matches.dn_data[0];
bv.bv_len = sizeof( buf ) - 1;
bv.bv_val = buf;
- switch ( a->acl_dn_style ) {
+ /* Expand value regex */
+ if ( a->acl_attrval_style == ACL_STYLE_REGEX )
+ tmp_matchesp = matches;
+ else switch ( a->acl_dn_style ) {
case ACL_STYLE_REGEX:
if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
tmp_matchesp = matches;
- tmp_nmatch = nmatch;
break;
}
/* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */
case ACL_STYLE_BASE:
- tmp_matches[0].rm_so = 0;
- tmp_matches[0].rm_eo = e->e_nname.bv_len;
- tmp_nmatch = 1;
+ tmp_data[0].rm_so = 0;
+ tmp_data[0].rm_eo = e->e_nname.bv_len;
+ tmp_matches.dn_count = 1;
break;
case ACL_STYLE_ONE:
case ACL_STYLE_SUBTREE:
case ACL_STYLE_CHILDREN:
- tmp_matches[0].rm_so = 0;
- tmp_matches[0].rm_eo = e->e_nname.bv_len;
- tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
- tmp_matches[1].rm_eo = e->e_nname.bv_len;
- tmp_nmatch = 2;
+ tmp_data[0].rm_so = 0;
+ tmp_data[0].rm_eo = e->e_nname.bv_len;
+ tmp_data[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
+ tmp_data[1].rm_eo = e->e_nname.bv_len;
+ tmp_matches.dn_count = 2;
break;
default:
}
if ( acl_string_expand( &bv, &bdn->a_pat,
- e->e_nname.bv_val,
- tmp_nmatch, tmp_matchesp ) )
+ &e->e_nname,
+ val, tmp_matchesp ) )
{
return 1;
}
Entry *e,
struct berval *val,
AccessControl *a,
- Access *b,
- int i,
- regmatch_t *matches,
int count,
AccessControlState *state,
+ slap_mask_t *mask,
slap_dn_access *bdn,
struct berval *opndn )
{
at != NULL;
at = attrs_find( at->a_next, bdn->a_at ) )
{
- if ( value_find_ex( bdn->a_at,
+ if ( attr_valfind( at,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
- at->a_nvals,
- &bv, op->o_tmpmemctx ) == 0 )
+ &bv, NULL, op->o_tmpmemctx ) == 0 )
{
/* found it */
match = 1;
Entry *e,
AttributeDescription *desc,
struct berval *val,
- int nmatch,
- regmatch_t *matches,
+ AclRegexMatches *matches,
int count,
- AccessControlState *state )
+ AccessControlState *state,
+ slap_access_t access )
{
int i;
Access *b;
char accessmaskbuf[ACCESSMASK_MAXLEN];
#endif /* DEBUG */
const char *attr;
- slap_mask_t a2pmask = ACL_ACCESS2PRIV( *mask );
+#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, nmatch, 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, nmatch, 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, nmatch, 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, nmatch, 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, nmatch, 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, nmatch, 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, nmatch, 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, nmatch, matches ) )
+ if ( acl_string_expand( &bv, &b->a_peername_pat, &e->e_nname, val, matches ) )
{
continue;
}
/* extract IP and try exact match */
} else if ( b->a_peername_style == ACL_STYLE_IP ) {
char *port;
- char buf[] = "255.255.255.255";
+ char buf[STRLENOF("255.255.255.255") + 1];
struct berval ip;
unsigned long addr;
int port_number = -1;
if ( (addr & b->a_peername_mask) != b->a_peername_addr )
continue;
+#ifdef LDAP_PF_INET6
+ /* extract IPv6 and try exact match */
+ } else if ( b->a_peername_style == ACL_STYLE_IPV6 ) {
+ char *port;
+ char buf[STRLENOF("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF") + 1];
+ struct berval ip;
+ struct in6_addr addr;
+ int port_number = -1;
+
+ if ( strncasecmp( op->o_conn->c_peer_name.bv_val,
+ acl_bv_ipv6_eq.bv_val,
+ acl_bv_ipv6_eq.bv_len ) != 0 )
+ continue;
+
+ ip.bv_val = op->o_conn->c_peer_name.bv_val + acl_bv_ipv6_eq.bv_len;
+ ip.bv_len = op->o_conn->c_peer_name.bv_len - acl_bv_ipv6_eq.bv_len;
+
+ port = strrchr( ip.bv_val, ']' );
+ if ( port ) {
+ ip.bv_len = port - ip.bv_val;
+ ++port;
+ if ( port[0] == ':' && lutil_atoi( &port_number, ++port ) != 0 )
+ continue;
+ }
+
+ /* the port check can be anticipated here */
+ if ( b->a_peername_port != -1 && port_number != b->a_peername_port )
+ continue;
+
+ /* address longer than expected? */
+ if ( ip.bv_len >= sizeof(buf) )
+ continue;
+
+ AC_MEMCPY( buf, ip.bv_val, ip.bv_len );
+ buf[ ip.bv_len ] = '\0';
+
+ if ( inet_pton( AF_INET6, buf, &addr ) != 1 )
+ continue;
+
+ /* check mask */
+ if ( !slap_addr6_mask( &addr, &b->a_peername_mask6, &b->a_peername_addr6 ) )
+ continue;
+#endif /* LDAP_PF_INET6 */
+
#ifdef LDAP_PF_LOCAL
/* extract path and try exact match */
} else if ( b->a_peername_style == ACL_STYLE_PATH ) {
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, nmatch, 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, nmatch, 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;
/* see if asker is listed in dnattr */
if ( b->a_group_style == ACL_STYLE_EXPAND ) {
char buf[ACL_BUF_SIZE];
- int tmp_nmatch;
- regmatch_t tmp_matches[2],
- *tmp_matchesp = tmp_matches;
+ AclRegexMatches tmp_matches,
+ *tmp_matchesp = &tmp_matches;
+ regmatch_t *tmp_data;
+
+ MATCHES_MEMSET( &tmp_matches );
+ tmp_data = &tmp_matches.dn_data[0];
bv.bv_len = sizeof(buf) - 1;
bv.bv_val = buf;
rc = 0;
- switch ( a->acl_dn_style ) {
+ if ( a->acl_attrval_style == ACL_STYLE_REGEX )
+ tmp_matchesp = matches;
+ else switch ( a->acl_dn_style ) {
case ACL_STYLE_REGEX:
if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
tmp_matchesp = matches;
- tmp_nmatch = nmatch;
break;
}
/* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */
case ACL_STYLE_BASE:
- tmp_matches[0].rm_so = 0;
- tmp_matches[0].rm_eo = e->e_nname.bv_len;
- tmp_nmatch = 1;
+ tmp_data[0].rm_so = 0;
+ tmp_data[0].rm_eo = e->e_nname.bv_len;
+ tmp_matches.dn_count = 1;
break;
case ACL_STYLE_ONE:
case ACL_STYLE_SUBTREE:
case ACL_STYLE_CHILDREN:
- tmp_matches[0].rm_so = 0;
- tmp_matches[0].rm_eo = e->e_nname.bv_len;
- tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
- tmp_matches[1].rm_eo = e->e_nname.bv_len;
- tmp_nmatch = 2;
+ tmp_data[0].rm_so = 0;
+ tmp_data[0].rm_eo = e->e_nname.bv_len;
+
+ tmp_data[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
+ tmp_data[1].rm_eo = e->e_nname.bv_len;
+ tmp_matches.dn_count = 2;
break;
default:
}
if ( acl_string_expand( &bv, &b->a_group_pat,
- e->e_nname.bv_val,
- tmp_nmatch, tmp_matchesp ) )
+ &e->e_nname, val,
+ tmp_matchesp ) )
{
continue;
}
b->a_set_pat.bv_val, 0, 0 );
if ( b->a_set_style == ACL_STYLE_EXPAND ) {
- int tmp_nmatch;
- regmatch_t tmp_matches[2],
- *tmp_matchesp = tmp_matches;
+ AclRegexMatches tmp_matches,
+ *tmp_matchesp = &tmp_matches;
int rc = 0;
+ regmatch_t *tmp_data;
+
+ MATCHES_MEMSET( &tmp_matches );
+ tmp_data = &tmp_matches.dn_data[0];
bv.bv_len = sizeof( buf ) - 1;
bv.bv_val = buf;
rc = 0;
- switch ( a->acl_dn_style ) {
+ if ( a->acl_attrval_style == ACL_STYLE_REGEX )
+ tmp_matchesp = matches;
+ else switch ( a->acl_dn_style ) {
case ACL_STYLE_REGEX:
if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
tmp_matchesp = matches;
- tmp_nmatch = nmatch;
break;
}
/* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */
case ACL_STYLE_BASE:
- tmp_matches[0].rm_so = 0;
- tmp_matches[0].rm_eo = e->e_nname.bv_len;
- tmp_nmatch = 1;
+ tmp_data[0].rm_so = 0;
+ tmp_data[0].rm_eo = e->e_nname.bv_len;
+ tmp_matches.dn_count = 1;
break;
case ACL_STYLE_ONE:
case ACL_STYLE_SUBTREE:
case ACL_STYLE_CHILDREN:
- tmp_matches[0].rm_so = 0;
- tmp_matches[0].rm_eo = e->e_nname.bv_len;
- tmp_matches[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
- tmp_matches[1].rm_eo = e->e_nname.bv_len;
- tmp_nmatch = 2;
+ tmp_data[0].rm_so = 0;
+ tmp_data[0].rm_eo = e->e_nname.bv_len;
+ tmp_data[1].rm_so = e->e_nname.bv_len - a->acl_dn_pat.bv_len;
+ tmp_data[1].rm_eo = e->e_nname.bv_len; tmp_matches.dn_count = 2;
break;
default:
}
if ( acl_string_expand( &bv, &b->a_set_pat,
- e->e_nname.bv_val,
- tmp_nmatch, tmp_matchesp ) )
+ &e->e_nname, val,
+ tmp_matchesp ) )
{
continue;
}
Debug( LDAP_DEBUG_ACL, " <= check a_dynacl: %s\n",
da->da_name, 0, 0 );
- (void)( *da->da_mask )( da->da_private, op, e, desc, val, nmatch, matches, &grant, &deny );
+ /*
+ * XXXmanu Only DN matches are supplied
+ * sending attribute values matches require
+ * an API update
+ */
+ (void)da->da_mask( da->da_private, op, e, desc,
+ val, matches->dn_count, matches->dn_data,
+ &grant, &deny );
tgrant |= grant;
tdeny |= deny;
*mask = modmask;
}
- a2pmask = *mask;
-
Debug( LDAP_DEBUG_ACL,
"<= acl_mask: [%d] mask: %s\n",
i, accessmask2str(*mask, accessmaskbuf, 1), 0 );
}
assert( be != NULL );
+ /* If ADD attribute checking is not enabled, just allow it */
+ if ( op->o_tag == LDAP_REQ_ADD && !SLAP_DBACL_ADD( be ))
+ return 1;
+
/* short circuit root database access */
if ( be_isroot( op ) ) {
Debug( LDAP_DEBUG_ACL,
}
/* use backend default access if no backend acls */
- if( op->o_bd != NULL && op->o_bd->be_acl == NULL ) {
+ if( op->o_bd != NULL && op->o_bd->be_acl == NULL && frontendDB->be_acl == NULL ) {
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: backend default %s access %s to \"%s\"\n",
access2str( ACL_WRITE ),
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;
for ( j = 0; !BER_BVISNULL( &rs->sr_attrs[ j ].an_name ); j++ ) {
AttributeDescription *desc = rs->sr_attrs[ j ].an_desc;
+
+ if ( desc == NULL ) {
+ continue;
+ }
if ( desc == slap_schema.si_ad_entryDN ) {
bvalsp = bvals;
a = attr_find( rs->sr_entry->e_attrs, desc );
if ( a != NULL ) {
- int i;
-
- for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ )
- ;
-
bvalsp = a->a_nvals;
}
}
- }
- if ( bvals ) {
- p->bvals = slap_set_join( p->cookie, p->bvals,
- ( '|' | SLAP_SET_RREF ), bvalsp );
+ if ( bvalsp ) {
+ p->bvals = slap_set_join( p->cookie, p->bvals,
+ ( '|' | SLAP_SET_RREF ), bvalsp );
+ }
}
} else {
int nattrs = 0;
slap_callback cb = { NULL, acl_set_cb_gather, NULL, NULL };
acl_set_gather_t p = { 0 };
- const char *text = NULL;
- static struct berval defaultFilter_bv = BER_BVC( "(objectClass=*)" );
/* this routine needs to return the bervals instead of
* plain strings, since syntax is not known. It should
rc = ldap_url_parse( name->bv_val, &ludp );
if ( rc != LDAP_URL_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "%s acl_set_gather: unable to parse URL=\"%s\"\n",
+ cp->asc_op->o_log_prefix, name->bv_val, 0 );
+
rc = LDAP_PROTOCOL_ERROR;
goto url_done;
}
{
/* host part must be empty */
/* extensions parts must be empty */
+ Debug( LDAP_DEBUG_TRACE,
+ "%s acl_set_gather: host/exts must be absent in URL=\"%s\"\n",
+ cp->asc_op->o_log_prefix, name->bv_val, 0 );
+
rc = LDAP_PROTOCOL_ERROR;
goto url_done;
}
&op2.o_req_ndn, cp->asc_op->o_tmpmemctx );
BER_BVZERO( &op2.o_req_dn );
if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "%s acl_set_gather: DN=\"%s\" normalize failed\n",
+ cp->asc_op->o_log_prefix, ludp->lud_dn, 0 );
+
goto url_done;
}
- op2.o_bd = select_backend( &op2.o_req_ndn, 0, 1 );
+ op2.o_bd = select_backend( &op2.o_req_ndn, 1 );
if ( ( op2.o_bd == NULL ) || ( op2.o_bd->be_search == NULL ) ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "%s acl_set_gather: no database could be selected for DN=\"%s\"\n",
+ cp->asc_op->o_log_prefix, op2.o_req_ndn.bv_val, 0 );
+
rc = LDAP_NO_SUCH_OBJECT;
goto url_done;
}
if ( ludp->lud_filter ) {
ber_str2bv_x( ludp->lud_filter, 0, 0, &op2.ors_filterstr,
cp->asc_op->o_tmpmemctx );
+ op2.ors_filter = str2filter_x( cp->asc_op, op2.ors_filterstr.bv_val );
+ if ( op2.ors_filter == NULL ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "%s acl_set_gather: unable to parse filter=\"%s\"\n",
+ cp->asc_op->o_log_prefix, op2.ors_filterstr.bv_val, 0 );
+
+ rc = LDAP_PROTOCOL_ERROR;
+ goto url_done;
+ }
} else {
- op2.ors_filterstr = defaultFilter_bv;
+ op2.ors_filterstr = *slap_filterstr_objectClass_pres;
+ op2.ors_filter = (Filter *)slap_filter_objectClass_pres;
}
- op2.ors_filter = str2filter_x( cp->asc_op, op2.ors_filterstr.bv_val );
- if ( op2.ors_filter == NULL ) {
- rc = LDAP_PROTOCOL_ERROR;
- goto url_done;
- }
/* Grab the scope */
op2.ors_scope = ludp->lud_scope;
/* Grap the attributes */
if ( ludp->lud_attrs ) {
+ int i;
+
for ( ; ludp->lud_attrs[ nattrs ]; nattrs++ )
;
- anlistp = slap_sl_malloc( sizeof( AttributeName ) * ( nattrs + 2 ),
+ anlistp = slap_sl_calloc( sizeof( AttributeName ), nattrs + 2,
cp->asc_op->o_tmpmemctx );
- for ( ; ludp->lud_attrs[ nattrs ]; nattrs++ ) {
- ber_str2bv( ludp->lud_attrs[ nattrs ], 0, 0, &anlistp[ nattrs ].an_name );
- anlistp[ nattrs ].an_desc = NULL;
- rc = slap_bv2ad( &anlistp[ nattrs ].an_name,
- &anlistp[ nattrs ].an_desc, &text );
- if ( rc != LDAP_SUCCESS ) {
- goto url_done;
+ for ( i = 0, nattrs = 0; ludp->lud_attrs[ i ]; i++ ) {
+ struct berval name;
+ AttributeDescription *desc = NULL;
+ const char *text = NULL;
+
+ ber_str2bv( ludp->lud_attrs[ i ], 0, 0, &name );
+ rc = slap_bv2ad( &name, &desc, &text );
+ if ( rc == LDAP_SUCCESS ) {
+ anlistp[ nattrs ].an_name = name;
+ anlistp[ nattrs ].an_desc = desc;
+ nattrs++;
}
}
op2.ors_attrs = anlistp;
op2.ors_attrsonly = 0;
op2.o_private = cp->asc_op->o_private;
+ op2.o_extra = cp->asc_op->o_extra;
cb.sc_private = &p;
}
url_done:;
- if ( op2.ors_filter ) {
- filter_free_x( cp->asc_op, op2.ors_filter );
+ if ( op2.ors_filter && op2.ors_filter != slap_filter_objectClass_pres ) {
+ filter_free_x( cp->asc_op, op2.ors_filter, 1 );
}
if ( !BER_BVISNULL( &op2.o_req_ndn ) ) {
slap_sl_free( op2.o_req_ndn.bv_val, cp->asc_op->o_tmpmemctx );
AclSetCookie cookie;
if ( default_set_attribute == NULL ) {
- ber_dupbv_x( &set, subj, op->o_tmpmemctx );
+ set = *subj;
} else {
struct berval subjdn, ndn = BER_BVNULL;
acl_set_gather,
(SetCookie *)&cookie, &set,
&op->o_ndn, &e->e_nname, NULL ) > 0 );
- slap_sl_free( set.bv_val, op->o_tmpmemctx );
+ if ( set.bv_val != subj->bv_val ) {
+ slap_sl_free( set.bv_val, op->o_tmpmemctx );
+ }
}
return(rc);
acl_string_expand(
struct berval *bv,
struct berval *pat,
- char *match,
- int nmatch,
- regmatch_t *matches)
+ struct berval *dn_matches,
+ struct berval *val_matches,
+ AclRegexMatches *matches)
{
ber_len_t size;
char *sp;
char *dp;
int flag;
+ enum { DN_FLAG, VAL_FLAG } tflag;
size = 0;
bv->bv_val[0] = '\0';
bv->bv_len--; /* leave space for lone $ */
flag = 0;
+ tflag = DN_FLAG;
for ( dp = bv->bv_val, sp = pat->bv_val; size < bv->bv_len &&
sp < pat->bv_val + pat->bv_len ; sp++ )
{
*dp++ = '$';
size++;
flag = 0;
+ tflag = DN_FLAG;
+
+ } else if ( flag == 2 && *sp == 'v' /*'}'*/) {
+ tflag = VAL_FLAG;
+
+ } else if ( flag == 2 && *sp == 'd' /*'}'*/) {
+ tflag = DN_FLAG;
} else if ( flag == 1 && *sp == '{' /*'}'*/) {
flag = 2;
} else if ( *sp >= '0' && *sp <= '9' ) {
+ int nm;
+ regmatch_t *m;
+ char *data;
int n;
int i;
int l;
}
}
- if ( n >= nmatch ) {
+ switch (tflag) {
+ case DN_FLAG:
+ nm = matches->dn_count;
+ m = matches->dn_data;
+ data = dn_matches ? dn_matches->bv_val : NULL;
+ break;
+ case VAL_FLAG:
+ nm = matches->val_count;
+ m = matches->val_data;
+ data = val_matches ? val_matches->bv_val : NULL;
+ break;
+ default:
+ assert( 0 );
+ }
+ if ( n >= nm ) {
+ /* FIXME: error */
+ return 1;
+ }
+ if ( data == NULL ) {
/* FIXME: error */
return 1;
}
*dp = '\0';
- i = matches[n].rm_so;
- l = matches[n].rm_eo;
+ i = m[n].rm_so;
+ l = m[n].rm_eo;
+
for ( ; size < bv->bv_len && i < l; size++, i++ ) {
- *dp++ = match[i];
+ *dp++ = data[i];
}
*dp = '\0';
flag = 0;
+ tflag = DN_FLAG;
}
} else {
if (*sp == '$') {
*dp = '\0';
bv->bv_len = size;
- Debug( LDAP_DEBUG_TRACE, "=> acl_string_expand: pattern: %.*s\n", (int)pat->bv_len, pat->bv_val, 0 );
- Debug( LDAP_DEBUG_TRACE, "=> acl_string_expand: expanded: %s\n", bv->bv_val, 0, 0 );
+ Debug( LDAP_DEBUG_ACL, "=> acl_string_expand: pattern: %.*s\n", (int)pat->bv_len, pat->bv_val, 0 );
+ Debug( LDAP_DEBUG_ACL, "=> acl_string_expand: expanded: %s\n", bv->bv_val, 0, 0 );
return 0;
}
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 */
- int nmatch, /* size of the matches array */
- regmatch_t *matches /* offsets in buffer for $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 */
)
{
regex_t re;
str = "";
};
- acl_string_expand( &bv, pat, buf, nmatch, 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];