Newer
Older
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* Portions Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of Michigan at Ann Arbor. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
#include <ac/regex.h>
#include <ac/socket.h>
#include <ac/string.h>
#include "sets.h"
#include "lber_pvt.h"
Pierangelo Masarati
committed
#ifdef LDAP_SLAPI
#include "slapi/slapi.h"
Pierangelo Masarati
committed
#endif /* LDAPI_SLAPI */
#define ACL_BUF_SIZE 1024 /* use most appropriate size */
Pierangelo Masarati
committed
/*
* speed up compares
*/
static struct berval
aci_bv_entry = BER_BVC("entry"),
aci_bv_br_entry = BER_BVC("[entry]"),
aci_bv_br_all = BER_BVC("[all]"),
aci_bv_access_id = BER_BVC("access-id"),
aci_bv_anonymous = BER_BVC("anonymous"),
aci_bv_public = BER_BVC("public"),
aci_bv_users = BER_BVC("users"),
aci_bv_self = BER_BVC("self"),
aci_bv_dnattr = BER_BVC("dnattr"),
aci_bv_group = BER_BVC("group"),
aci_bv_role = BER_BVC("role"),
aci_bv_set = BER_BVC("set"),
aci_bv_set_ref = BER_BVC("set-ref"),
aci_bv_grant = BER_BVC("grant"),
aci_bv_deny = BER_BVC("deny"),
aci_bv_ip_eq = BER_BVC("IP="),
#ifdef LDAP_PF_LOCAL
aci_bv_path_eq = BER_BVC("PATH="),
aci_bv_dirsep = BER_BVC(LDAP_DIRSEP),
#endif /* LDAP_PF_LOCAL */
aci_bv_group_class = BER_BVC(SLAPD_GROUP_CLASS),
aci_bv_group_attr = BER_BVC(SLAPD_GROUP_ATTR),
aci_bv_role_class = BER_BVC(SLAPD_ROLE_CLASS),
aci_bv_role_attr = BER_BVC(SLAPD_ROLE_ATTR),
aci_bv_set_attr = BER_BVC(SLAPD_ACI_SET_ATTR);
Pierangelo Masarati
committed
static AccessControl * acl_get(
AccessControl *ac, int *count,
Operation *op, Entry *e,
int nmatches, regmatch_t *matches,
AccessControlState *state );
static slap_control_t acl_mask(
Operation *op, Entry *e,
struct berval *val,
regmatch_t *matches,
int count,
AccessControlState *state );
#ifdef SLAPD_ACI_ENABLED
static int aci_mask(
Operation *op, Entry *e,
struct berval *val,
struct berval *aci,
regmatch_t *matches,
slap_access_t *grant,
slap_access_t *deny,
struct berval *scope);
static int regex_matches(
struct berval *pat, char *str, char *buf, regmatch_t *matches);
static void string_expand(
struct berval *newbuf, struct berval *pattern,
char *match, regmatch_t *matches);
typedef struct AciSetCookie {
Operation *op;
static int aci_match_set ( struct berval *subj, Operation *op,
Entry *e, int setref );
* access_allowed - check whether op->o_ndn is allowed the requested access
* to entry e, attribute attr, value val. if val is null, access to
* the whole attribute is assumed (all values).
* This routine loops through all access controls and calls
* acl_mask() on each applicable access control.
* The loop exits when a definitive answer is reached or
* or no more controls remain.
*
* returns:
* 0 access denied
* 1 access granted
Pierangelo Masarati
committed
*
* Notes:
* - can be legally called with op == NULL
* - can be legally called with op->o_bd == NULL
Operation *op,
Entry *e,
AttributeDescription *desc,
struct berval *val,
slap_access_t access,
AccessControlState *state,
slap_mask_t *maskp )
int count;
AccessControl *a = NULL;
#ifdef LDAP_DEBUG
slap_control_t control;
const char *attr;
regmatch_t matches[MAXREMATCHES];
int st_same_attr = 0;
static AccessControlState state_init = ACL_STATE_INIT;
assert( e != NULL );
assert( desc != NULL );
assert( access > ACL_NONE );
attr = desc->ad_cname.bv_val;
assert( attr != NULL );
if( op && op->o_is_auth_check &&
( access == ACL_SEARCH || access == ACL_READ ))
{
access = ACL_AUTH;
}
if( state ) {
if ( state->as_vd_ad==desc) {
if ( 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;
}
}
st_same_attr = 1;
} else {
*state = state_init;
LDAP_LOG( ACL, ENTRY,
"access_allowed: %s access to \"%s\" \"%s\" requested\n",
access2str( access ), e->e_dn, attr );
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: %s access to \"%s\" \"%s\" requested\n",
if ( op == NULL ) {
/* no-op call */
}
if ( be == NULL ) {
be = &backends[0];
#ifdef LDAP_DEVEL
/*
* FIXME: experimental; use first backend rules
* iff there is no global_acl (ITS#3100) */
if ( global_acl == NULL )
#endif
{
op->o_bd = be;
}
}
assert( be != NULL );
if ( op->o_pb != NULL ) {
ret = slapi_int_access_allowed( op, e, desc, val, access, state );
if ( ret == 0 ) {
/* ACL plugin denied access */
goto done;
}
/* grant database root access */
if ( be != NULL && be_isroot( op ) ) {
LDAP_LOG( ACL, INFO,
"access_allowed: conn %lu root access granted\n",
op->o_connid, 0, 0 );
Debug( LDAP_DEBUG_ACL,
"<= root access granted\n",
0, 0, 0 );
if ( maskp ) {
mask = ACL_LVL_WRITE;
}
/*
* no-user-modification operational attributes are ignored
* by ACL_WRITE checking as any found here are not provided
* by the user
*/
if ( access >= ACL_WRITE && is_at_no_user_mod( desc->ad_type )
&& desc != slap_schema.si_ad_entry
&& desc != slap_schema.si_ad_children )
LDAP_LOG( ACL, DETAIL1,
"access_allowed: conn %lu NoUserMod Operational attribute: %s "
"access granted\n", op->o_connid, attr , 0 );
" %s access granted\n",
attr, 0, 0 );
}
/* use backend default access if no backend acls */
if( be != NULL && be->be_acl == NULL ) {
LDAP_LOG( ACL, DETAIL1,
"access_allowed: backend default %s access %s to \"%s\"\n",
access2str( access ),
be->be_dfltaccess >= access ? "granted" : "denied",
op->o_dn.bv_val ? op->o_dn.bv_val : "(anonymous)" );
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: backend default %s access %s to \"%s\"\n",
access2str( access ),
be->be_dfltaccess >= access ? "granted" : "denied",
op->o_dn.bv_val ? op->o_dn.bv_val : "(anonymous)" );
ret = be->be_dfltaccess >= access;
if ( maskp ) {
int i;
mask = ACL_PRIV_LEVEL;
for ( i = ACL_NONE; i <= be->be_dfltaccess; i++ ) {
#ifdef notdef
/* be is always non-NULL */
/* use global default access if no global acls */
} else if ( be == NULL && global_acl == NULL ) {
LDAP_LOG( ACL, DETAIL1,
"access_allowed: global default %s access %s to \"%s\"\n",
access2str( access ),
global_default_access >= access ? "granted" : "denied",
op->o_dn.bv_val );
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: global default %s access %s to \"%s\"\n",
access2str( access ),
global_default_access >= access ? "granted" : "denied", op->o_dn.bv_val );
ret = global_default_access >= access;
if ( maskp ) {
int i;
mask = ACL_PRIV_LEVEL;
for ( i = ACL_NONE; i <= global_default_access; i++ ) {
mask |= ACL_ACCESS2PRIV( i );
}
}
#endif
control = ACL_BREAK;
assert( state->as_vd_acl != NULL );
a = state->as_vd_acl;
count = state->as_vd_acl_count;
if ( !ACL_IS_INVALID( state->as_vd_acl_mask )) {
mask = state->as_vd_acl_mask;
AC_MEMCPY( matches, state->as_vd_acl_matches, sizeof(matches) );
goto vd_access;
}
if ( state ) state->as_vi_acl = NULL;
a = NULL;
ACL_INIT(mask);
count = 0;
memset(matches, '\0', sizeof(matches));
}
while((a = acl_get( a, &count, op, e, desc, val,
{
int i;
for (i = 0; i < MAXREMATCHES && matches[i].rm_so > 0; i++) {
LDAP_LOG( ACL, DETAIL1,
"access_allowed: match[%d]: %d %d ",
i, (int)matches[i].rm_so, (int)matches[i].rm_eo );
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 n;
for ( n = matches[i].rm_so; n < matches[i].rm_eo; n++) {
Debug( LDAP_DEBUG_ACL, "%c", e->e_ndn[n], 0, 0 );
}
}
Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );
if (state) {
if (state->as_vi_acl == a && (state->as_recorded & ACL_STATE_RECORDED_NV)) {
Debug( LDAP_DEBUG_ACL, "access_allowed: result from state (%s)\n", attr, 0, 0 );
ret = state->as_result;
goto done;
Debug( LDAP_DEBUG_ACL, "access_allowed: no res from state (%s)\n", attr, 0, 0);
}
}
control = acl_mask( a, &mask, op,
e, desc, val, matches, count, state );
if ( control != ACL_BREAK ) {
break;
}
if ( ACL_IS_INVALID( mask ) ) {
LDAP_LOG( ACL, DETAIL1,
"access_allowed: conn %lu \"%s\" (%s) invalid!\n",
op->o_connid, e->e_dn, attr );
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: \"%s\" (%s) invalid!\n",
e->e_dn, attr, 0 );
} else if ( control == ACL_BREAK ) {
"access_allowed: conn %lu no more rules\n", op->o_connid, 0,0 );
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: no more rules\n", 0, 0, 0);
LDAP_LOG( ACL, ENTRY,
"access_allowed: %s access %s by %s\n",
access2str( access ), ACL_GRANT( mask, access ) ? "granted" : "denied",
accessmask2str( mask, accessmaskbuf ) );
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: %s access %s by %s\n",
access2str( access ),
ACL_GRANT(mask, access) ? "granted" : "denied",
accessmask2str( mask, accessmaskbuf ) );
ret = ACL_GRANT(mask, access);
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_recorded |= ACL_STATE_RECORDED;
}
* 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(
AccessControl *a,
int *count,
Operation *op,
Entry *e,
int dnlen, patlen;
assert( e != NULL );
assert( count != NULL );
assert( desc != NULL );
attr = desc->ad_cname.bv_val;
assert( attr != NULL );
if( a == NULL ) {
if( op->o_bd == NULL ) {
a = global_acl;
} else {
a = op->o_bd->be_acl;
assert( a != NULL );
} else {
a = a->acl_next;
for ( ; a != NULL; a = a->acl_next ) {
(*count) ++;
if ( a->acl_dn_pat.bv_len || ( a->acl_dn_style != ACL_STYLE_REGEX )) {
if ( a->acl_dn_style == ACL_STYLE_REGEX ) {
LDAP_LOG( ACL, DETAIL1,
"acl_get: dnpat [%d] %s nsub: %d\n",
*count, a->acl_dn_pat.bv_val,
(int) a->acl_dn_re.re_nsub );
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))
continue;
} else {
LDAP_LOG( ACL, DETAIL1, "acl_get: dn [%d] %s\n",
*count, a->acl_dn_pat.bv_val, 0 );
Debug( LDAP_DEBUG_ACL, "=> dn: [%d] %s\n",
patlen = a->acl_dn_pat.bv_len;
if ( dnlen < patlen )
continue;
if ( a->acl_dn_style == ACL_STYLE_BASE ) {
/* base dn -- entire object DN must match */
if ( dnlen != patlen )
continue;
} else if ( a->acl_dn_style == ACL_STYLE_ONE ) {
if ( dnlen <= patlen )
continue;
if ( !DN_SEPARATOR( e->e_ndn[dnlen - patlen - 1] ) )
rdnlen = dn_rdnlen( NULL, &e->e_nname );
continue;
} else if ( a->acl_dn_style == ACL_STYLE_SUBTREE ) {
if ( dnlen > patlen && !DN_SEPARATOR( e->e_ndn[dnlen - patlen - 1] ) )
continue;
} else if ( a->acl_dn_style == ACL_STYLE_CHILDREN ) {
if ( dnlen <= patlen )
continue;
if ( !DN_SEPARATOR( e->e_ndn[dnlen - patlen - 1] ) )
continue;
}
if ( strcmp( a->acl_dn_pat.bv_val, e->e_ndn + dnlen - patlen ) != 0 )
continue;
LDAP_LOG( ACL, DETAIL1,
"acl_get: [%d] matched\n", *count, 0, 0 );
Debug( LDAP_DEBUG_ACL, "=> acl_get: [%d] matched\n",
*count, 0, 0 );
if ( a->acl_attrs && !ad_inlist( desc, a->acl_attrs ) ) {
matches[0].rm_so = matches[0].rm_eo = -1;
continue;
}
/* Is this ACL only for a specific value? */
if ( a->acl_attrval.bv_len ) {
if ( val == NULL ) {
continue;
}
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_count = *count;
state->as_vd_access = a->acl_access;
state->as_vd_access_count = 1;
ACL_INVALIDATE( state->as_vd_acl_mask );
}
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
if ( a->acl_attrval_style == ACL_STYLE_REGEX ) {
#ifdef NEW_LOGGING
LDAP_LOG( ACL, DETAIL1,
"acl_get: valpat %s\n",
a->acl_attrval.bv_val, 0, 0 );
#else
Debug( LDAP_DEBUG_ACL,
"acl_get: valpat %s\n",
a->acl_attrval.bv_val, 0, 0 );
#endif
if (regexec(&a->acl_attrval_re, val->bv_val, 0, NULL, 0))
continue;
} else {
int match = 0;
const char *text;
#ifdef NEW_LOGGING
LDAP_LOG( ACL, DETAIL1,
"acl_get: val %s\n",
a->acl_attrval.bv_val, 0, 0 );
#else
Debug( LDAP_DEBUG_ACL,
"acl_get: val %s\n",
a->acl_attrval.bv_val, 0, 0 );
#endif
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,
val, &a->acl_attrval, &text ) != LDAP_SUCCESS ||
match )
continue;
} else {
int patlen, vdnlen;
patlen = a->acl_attrval.bv_len;
vdnlen = val->bv_len;
if ( vdnlen < patlen )
continue;
if ( a->acl_dn_style == ACL_STYLE_BASE ) {
if ( vdnlen > patlen )
continue;
} else if ( a->acl_dn_style == ACL_STYLE_ONE ) {
int rdnlen = -1;
if ( !DN_SEPARATOR( val->bv_val[vdnlen - patlen - 1] ) )
continue;
rdnlen = dn_rdnlen( NULL, val );
if ( rdnlen != vdnlen - patlen - 1 )
continue;
} else if ( a->acl_dn_style == ACL_STYLE_SUBTREE ) {
if ( vdnlen > patlen && !DN_SEPARATOR( val->bv_val[vdnlen - patlen - 1] ) )
continue;
} else if ( a->acl_dn_style == ACL_STYLE_CHILDREN ) {
if ( vdnlen <= patlen )
continue;
if ( !DN_SEPARATOR( val->bv_val[vdnlen - patlen - 1] ) )
continue;
}
if ( strcmp( a->acl_attrval.bv_val, val->bv_val + vdnlen - patlen ))
continue;
}
}
}
ber_int_t rc = test_filter( NULL, e, a->acl_filter );
if ( rc != LDAP_COMPARE_TRUE ) {
"acl_get: [%d] attr %s\n", *count, attr ,0 );
Debug( LDAP_DEBUG_ACL, "=> acl_get: [%d] attr %s\n",
Debug( LDAP_DEBUG_ACL, "<= acl_get: done.\n", 0, 0, 0 );
/*
* 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
* requested access to entry e, attribute attr, value val. if val
* is null, access to the whole attribute is assumed (all values).
*
* returns 0 access NOT allowed
* 1 access allowed
*/
static slap_control_t
acl_mask(
AccessControl *a,
Operation *op,
Entry *e,
AttributeDescription *desc,
struct berval *val,
regmatch_t *matches,
int count,
AccessControlState *state )
int i, odnlen, patlen;
#ifdef LDAP_DEBUG
const char *attr;
assert( a != NULL );
assert( mask != NULL );
assert( desc != NULL );
attr = desc->ad_cname.bv_val;
assert( attr != NULL );
LDAP_LOG( ACL, ENTRY,
"acl_mask: conn %lu access to entry \"%s\", attr \"%s\" requested\n",
op->o_connid, e->e_dn, attr );
LDAP_LOG( ACL, ARGS,
" to %s by \"%s\", (%s) \n", val ? "value" : "all values",
op->o_ndn.bv_val ? op->o_ndn.bv_val : "",
accessmask2str( *mask, accessmaskbuf ) );
Debug( LDAP_DEBUG_ACL,
"=> acl_mask: access to entry \"%s\", attr \"%s\" requested\n",
e->e_dn, attr, 0 );
Debug( LDAP_DEBUG_ACL,
"=> acl_mask: to %s by \"%s\", (%s) \n",
val ? "value" : "all values",
op->o_ndn.bv_val ? op->o_ndn.bv_val : "",
accessmask2str( *mask, accessmaskbuf ) );
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++ ) {
ACL_INVALIDATE( modmask );
if ( b->a_dn_pat.bv_len != 0 ) {
LDAP_LOG( ACL, DETAIL1,
"acl_mask: conn %lu check a_dn_pat: %s\n",
op->o_connid, b->a_dn_pat.bv_val ,0 );
Debug( LDAP_DEBUG_ACL, "<= check a_dn_pat: %s\n",
b->a_dn_pat.bv_val, 0, 0);
/*
* if access applies to the entry itself, and the
* user is bound as somebody in the same namespace as
* the entry, OR the given dn matches the dn pattern
*/
Pierangelo Masarati
committed
if ( bvmatch( &b->a_dn_pat, &aci_bv_anonymous ) ) {
Pierangelo Masarati
committed
if ( op->o_ndn.bv_len != 0 ) {
Pierangelo Masarati
committed
} else if ( bvmatch( &b->a_dn_pat, &aci_bv_users ) ) {
Pierangelo Masarati
committed
if ( op->o_ndn.bv_len == 0 ) {
Pierangelo Masarati
committed
} else if ( bvmatch( &b->a_dn_pat, &aci_bv_self ) ) {
Pierangelo Masarati
committed
if ( op->o_ndn.bv_len == 0 ) {
Pierangelo Masarati
committed
if ( e->e_dn == NULL || !dn_match( &e->e_nname, &op->o_ndn ) ) {
} else if ( b->a_dn_style == ACL_STYLE_REGEX ) {
Pierangelo Masarati
committed
if ( !ber_bvccmp( &b->a_dn_pat, '*' ) ) {
int ret = regex_matches( &b->a_dn_pat,
op->o_ndn.bv_val, e->e_ndn, matches );
if( ret == 0 ) {
continue;
}
}
} else {
Pierangelo Masarati
committed
struct berval pat;
int got_match = 0;
if ( e->e_dn == NULL )
continue;
Pierangelo Masarati
committed
if ( b->a_dn_expand ) {
struct berval bv;
char buf[ACL_BUF_SIZE];
Pierangelo Masarati
committed
bv.bv_len = sizeof( buf ) - 1;
bv.bv_val = buf;
string_expand(&bv, &b->a_dn_pat,
e->e_ndn, matches);
if ( dnNormalize(0, NULL, NULL, &bv, &pat, op->o_tmpmemctx ) != LDAP_SUCCESS ) {
Pierangelo Masarati
committed
/* did not expand to a valid dn */
continue;
}
} else {
pat = b->a_dn_pat;
}
patlen = pat.bv_len;
odnlen = op->o_ndn.bv_len;
Pierangelo Masarati
committed
if ( odnlen < patlen ) {
goto dn_match_cleanup;
}
if ( b->a_dn_style == ACL_STYLE_BASE ) {
/* base dn -- entire object DN must match */
Pierangelo Masarati
committed
if ( odnlen != patlen ) {
goto dn_match_cleanup;
}
} else if ( b->a_dn_style == ACL_STYLE_ONE ) {
int rdnlen = -1;
Pierangelo Masarati
committed
if ( odnlen <= patlen ) {
goto dn_match_cleanup;
}
if ( !DN_SEPARATOR( op->o_ndn.bv_val[odnlen - patlen - 1] ) ) {
Pierangelo Masarati
committed
goto dn_match_cleanup;
}
rdnlen = dn_rdnlen( NULL, &op->o_ndn );
Pierangelo Masarati
committed
if ( rdnlen != odnlen - patlen - 1 ) {
goto dn_match_cleanup;
}
} else if ( b->a_dn_style == ACL_STYLE_SUBTREE ) {
if ( odnlen > patlen && !DN_SEPARATOR( op->o_ndn.bv_val[odnlen - patlen - 1] ) ) {
Pierangelo Masarati
committed
goto dn_match_cleanup;
}
} else if ( b->a_dn_style == ACL_STYLE_CHILDREN ) {
Pierangelo Masarati
committed
if ( odnlen <= patlen ) {
goto dn_match_cleanup;
}
if ( !DN_SEPARATOR( op->o_ndn.bv_val[odnlen - patlen - 1] ) ) {
Pierangelo Masarati
committed
goto dn_match_cleanup;
}
Pierangelo Masarati
committed
got_match = !strcmp( pat.bv_val, op->o_ndn.bv_val + odnlen - patlen );
dn_match_cleanup:;
if ( pat.bv_val != b->a_dn_pat.bv_val ) {
free( pat.bv_val );
}
if ( !got_match ) {
continue;
Pierangelo Masarati
committed
}
if ( b->a_sockurl_pat.bv_len ) {
if ( ! op->o_conn->c_listener ) {
continue;
}
"acl_mask: conn %lu check a_sockurl_pat: %s\n",
op->o_connid, b->a_sockurl_pat.bv_val , 0 );
Debug( LDAP_DEBUG_ACL, "<= check a_sockurl_pat: %s\n",
b->a_sockurl_pat.bv_val, 0, 0 );
Pierangelo Masarati
committed
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 ) )
{
continue;
}
Pierangelo Masarati
committed
} else if ( b->a_sockurl_style == ACL_STYLE_EXPAND ) {
struct berval bv;
char buf[ACL_BUF_SIZE];
bv.bv_len = sizeof( buf ) - 1;
bv.bv_val = buf;
string_expand( &bv, &b->a_sockurl_pat, e->e_ndn, matches );
if ( ber_bvstrcasecmp( &bv, &op->o_conn->c_listener_url ) != 0 ) {
continue;
}
} else {
if ( ber_bvstrcasecmp( &b->a_sockurl_pat, &op->o_conn->c_listener_url ) != 0 )
continue;
}
if ( b->a_domain_pat.bv_len ) {
if ( !op->o_conn->c_peer_domain.bv_val ) {
continue;
}
"acl_mask: conn %lu check a_domain_pat: %s\n",
op->o_connid, b->a_domain_pat.bv_val , 0 );
Debug( LDAP_DEBUG_ACL, "<= check a_domain_pat: %s\n",
b->a_domain_pat.bv_val, 0, 0 );
Pierangelo Masarati
committed
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 ) )
{
continue;
}
} else {
char buf[ACL_BUF_SIZE];
Pierangelo Masarati
committed
struct berval cmp = op->o_conn->c_peer_domain;
Pierangelo Masarati
committed
struct berval pat = b->a_domain_pat;
if ( b->a_domain_expand ) {
struct berval bv;
bv.bv_len = sizeof(buf) - 1;
Pierangelo Masarati
committed
bv.bv_val = buf;
string_expand(&bv, &b->a_domain_pat, e->e_ndn, matches);
pat = bv;
}
if ( b->a_domain_style == ACL_STYLE_SUBTREE ) {
int offset = cmp.bv_len - pat.bv_len;
if ( offset < 0 ) {
continue;
}