From 1cb6c196039f7b7c0c7bafa00913dfc42f82bb5c Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 11 Dec 2009 05:09:40 +0000 Subject: [PATCH] Preliminary checkin for new access_allowed() signature. Still need to update backends and overlays. --- servers/slapd/acl.c | 477 ++++++++++++++++-------------------- servers/slapd/backend.c | 79 +++--- servers/slapd/backover.c | 13 +- servers/slapd/bconfig.c | 45 ++-- servers/slapd/compare.c | 90 ++++--- servers/slapd/filterentry.c | 73 ++++-- servers/slapd/passwd.c | 14 +- servers/slapd/proto-slap.h | 41 +--- servers/slapd/result.c | 63 +++-- servers/slapd/sasl.c | 9 +- servers/slapd/slap.h | 77 +++--- servers/slapd/slapacl.c | 66 ++--- 12 files changed, 528 insertions(+), 519 deletions(-) diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index bbd89fbd38..558d10218e 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -48,23 +48,16 @@ static const struct berval acl_bv_path_eq = BER_BVC("PATH="); #endif /* LDAP_PF_LOCAL */ static AccessControl * slap_acl_get( - AccessControl *ac, int *count, - Operation *op, Entry *e, - AttributeDescription *desc, - struct berval *val, + Operation *op, AclCheck *ak, + AccessControl *ac, AclRegexMatches *matches, - slap_mask_t *mask, - AccessControlState *state ); + int *count ); static slap_control_t slap_acl_mask( - AccessControl *ac, slap_mask_t *mask, - Operation *op, Entry *e, - AttributeDescription *desc, - struct berval *val, + Operation *op, AclCheck *ak, + AccessControl *ac, AclRegexMatches *matches, - int count, - AccessControlState *state, - slap_access_t access ); + int count ); static int regex_matches( struct berval *pat, char *str, @@ -103,17 +96,10 @@ SLAP_SET_GATHER acl_set_gather2; int slap_access_always_allowed( Operation *op, - Entry *e, - AttributeDescription *desc, - struct berval *val, - slap_access_t access, - AccessControlState *state, - slap_mask_t *maskp ) + AclCheck *ak ) { - assert( maskp != NULL ); - /* assign all */ - ACL_LVL_ASSIGN_MANAGE( *maskp ); + ACL_LVL_ASSIGN_MANAGE( ak->ak_mask ); return 1; } @@ -132,12 +118,7 @@ slap_access_always_allowed( int slap_access_allowed( Operation *op, - Entry *e, - AttributeDescription *desc, - struct berval *val, - slap_access_t access, - AccessControlState *state, - slap_mask_t *maskp ) + AclCheck *ak ) { int ret = 1; int count; @@ -146,33 +127,34 @@ slap_access_allowed( #ifdef LDAP_DEBUG char accessmaskbuf[ACCESSMASK_MAXLEN]; #endif - slap_mask_t mask; slap_control_t control; slap_access_t access_level; + slap_mask_t oldmask; const char *attr; AclRegexMatches matches; AccessControlState acl_state = ACL_STATE_INIT; static AccessControlState state_init = ACL_STATE_INIT; assert( op != NULL ); - assert( e != NULL ); - assert( desc != NULL ); - assert( maskp != NULL ); + assert( ak != NULL ); + assert( ak->ak_e != NULL ); + assert( ak->ak_desc != NULL ); - access_level = ACL_LEVEL( access ); - attr = desc->ad_cname.bv_val; + access_level = ACL_LEVEL( ak->ak_access ); + attr = ak->ak_desc->ad_cname.bv_val; assert( attr != NULL ); - ACL_INIT( mask ); - /* grant database root access */ if ( be_isroot( op ) ) { Debug( LDAP_DEBUG_ACL, "<= root access granted\n", 0, 0, 0 ); - mask = ACL_LVL_MANAGE; + ak->ak_mask = ACL_LVL_MANAGE; goto done; } + oldmask = ak->ak_mask; + ACL_INIT( ak->ak_mask ); + /* * no-user-modification operational attributes are ignored * by ACL_WRITE checking as any found here are not provided @@ -183,9 +165,9 @@ slap_access_allowed( * manage data, so we need to check its privileges. */ if ( access_level == ACL_WRITE - && is_at_no_user_mod( desc->ad_type ) - && desc != slap_schema.si_ad_entry - && desc != slap_schema.si_ad_children ) + && is_at_no_user_mod( ak->ak_desc->ad_type ) + && ak->ak_desc != slap_schema.si_ad_entry + && ak->ak_desc != slap_schema.si_ad_children ) { Debug( LDAP_DEBUG_ACL, "NoUserMod Operational attribute:" " %s access granted\n", @@ -200,14 +182,14 @@ slap_access_allowed( Debug( LDAP_DEBUG_ACL, "=> slap_access_allowed: backend default %s " "access %s to \"%s\"\n", - access2str( access ), + access2str( ak->ak_access ), op->o_bd->be_dfltaccess >= access_level ? "granted" : "denied", op->o_dn.bv_val ? op->o_dn.bv_val : "(anonymous)" ); ret = op->o_bd->be_dfltaccess >= access_level; - mask = ACL_PRIV_LEVEL; + ak->ak_mask = ACL_PRIV_LEVEL; for ( i = ACL_NONE; i <= op->o_bd->be_dfltaccess; i++ ) { - ACL_PRIV_SET( mask, ACL_ACCESS2PRIV( i ) ); + ACL_PRIV_SET( ak->ak_mask, ACL_ACCESS2PRIV( i ) ); } goto done; @@ -216,29 +198,27 @@ slap_access_allowed( ret = 0; control = ACL_BREAK; - if ( state == NULL ) - state = &acl_state; - if ( state->as_desc == desc && - state->as_access == access && - state->as_vd_acl != NULL ) + if ( ak->ak_state == NULL ) + ak->ak_state = &acl_state; + if ( ak->ak_state->as_desc == ak->ak_desc && + ak->ak_state->as_access == ak->ak_access && + ak->ak_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 ); + a = ak->ak_state->as_vd_acl; + count = ak->ak_state->as_vd_acl_count; + if ( ak->ak_state->as_fe_done ) + ak->ak_state->as_fe_done--; + ACL_PRIV_ASSIGN( ak->ak_mask, ak->ak_state->as_vd_mask ); } else { - *state = state_init; + *ak->ak_state = state_init; a = NULL; count = 0; - ACL_PRIV_ASSIGN( mask, *maskp ); } MATCHES_MEMSET( &matches ); - while ( ( a = slap_acl_get( a, &count, op, e, desc, val, - &matches, &mask, state ) ) != NULL ) + while ( ( a = slap_acl_get( op, ak, a, &matches, &count ) ) != NULL ) { int i; int dnmaxcount = MATCHES_DNMAXCOUNT( &matches ); @@ -248,7 +228,7 @@ slap_access_allowed( /* DN matches */ for ( i = 0; i < dnmaxcount && dn_data[i].rm_eo > 0; i++ ) { - char *data = e->e_ndn; + char *data = ak->ak_e->e_ndn; Debug( LDAP_DEBUG_ACL, "=> match[dn%d]: %d %d ", i, (int)dn_data[i].rm_so, @@ -266,7 +246,7 @@ slap_access_allowed( /* val matches */ for ( i = 0; i < valmaxcount && val_data[i].rm_eo > 0; i++ ) { - char *data = val->bv_val; + char *data = ak->ak_val->bv_val; Debug( LDAP_DEBUG_ACL, "=> match[val%d]: %d %d ", i, (int)val_data[i].rm_so, @@ -282,8 +262,8 @@ slap_access_allowed( Debug( LDAP_DEBUG_ACL, "\n", 0, 0, 0 ); } - control = slap_acl_mask( a, &mask, op, - e, desc, val, &matches, count, state, access ); + control = slap_acl_mask( op, ak, a, + &matches, count ); if ( control != ACL_BREAK ) { break; @@ -292,11 +272,11 @@ slap_access_allowed( MATCHES_MEMSET( &matches ); } - if ( ACL_IS_INVALID( mask ) ) { + if ( ACL_IS_INVALID( ak->ak_mask ) ) { Debug( LDAP_DEBUG_ACL, "=> slap_access_allowed: \"%s\" (%s) invalid!\n", - e->e_dn, attr, 0 ); - ACL_PRIV_ASSIGN( mask, *maskp ); + ak->ak_e->e_dn, attr, 0 ); + ACL_PRIV_ASSIGN( ak->ak_mask, oldmask ); } else if ( control == ACL_BREAK ) { Debug( LDAP_DEBUG_ACL, @@ -305,27 +285,23 @@ slap_access_allowed( goto done; } - ret = ACL_GRANT( mask, access ); + ret = ACL_GRANT( ak->ak_mask, ak->ak_access ); Debug( LDAP_DEBUG_ACL, "=> slap_access_allowed: %s access %s by %s\n", - access2str( access ), ret ? "granted" : "denied", - accessmask2str( mask, accessmaskbuf, 1 ) ); + access2str( ak->ak_access ), ret ? "granted" : "denied", + accessmask2str( ak->ak_mask, accessmaskbuf, 1 ) ); done: - ACL_PRIV_ASSIGN( *maskp, mask ); + if ( ak->ak_state == &acl_state ) + ak->ak_state = NULL; return ret; } int fe_access_allowed( Operation *op, - Entry *e, - AttributeDescription *desc, - struct berval *val, - slap_access_t access, - AccessControlState *state, - slap_mask_t *maskp ) + AclCheck *ak ) { BackendDB *be_orig; int rc; @@ -345,21 +321,16 @@ fe_access_allowed( if ( op->o_bd == NULL ) op->o_bd = frontendDB; } - rc = slap_access_allowed( op, e, desc, val, access, state, maskp ); + rc = slap_access_allowed( op, ak ); op->o_bd = be_orig; return rc; } int -access_allowed_mask( +access_allowed( Operation *op, - Entry *e, - AttributeDescription *desc, - struct berval *val, - slap_access_t access, - AccessControlState *state, - slap_mask_t *maskp ) + AclCheck *ak ) { int ret = 1; int be_null = 0; @@ -367,50 +338,49 @@ access_allowed_mask( #ifdef LDAP_DEBUG char accessmaskbuf[ACCESSMASK_MAXLEN]; #endif - slap_mask_t mask; - slap_access_t access_level; + slap_access_t access_level; const char *attr; - assert( e != NULL ); - assert( desc != NULL ); + assert( ak != NULL ); + assert( ak->ak_e != NULL ); + assert( ak->ak_desc != NULL ); - access_level = ACL_LEVEL( access ); + access_level = ACL_LEVEL( ak->ak_access ); assert( access_level > ACL_NONE ); - ACL_INIT( mask ); - if ( maskp ) ACL_INVALIDATE( *maskp ); + ACL_INVALIDATE( ak->ak_mask ); - attr = desc->ad_cname.bv_val; + attr = ak->ak_desc->ad_cname.bv_val; assert( attr != NULL ); if ( op ) { if ( op->o_acl_priv != ACL_NONE ) { - access = op->o_acl_priv; + ak->ak_access = op->o_acl_priv; } else if ( op->o_is_auth_check && ( access_level == ACL_SEARCH || access_level == ACL_READ ) ) { - access = ACL_AUTH; + ak->ak_access = ACL_AUTH; } else if ( get_relax( op ) && access_level == ACL_WRITE && - desc == slap_schema.si_ad_entry ) + ak->ak_desc == slap_schema.si_ad_entry ) { - access = ACL_MANAGE; + ak->ak_access = ACL_MANAGE; } } - if ( state != NULL ) { - if ( state->as_desc == desc && - state->as_access == access && - state->as_result != -1 && - state->as_vd_acl == NULL ) + if ( ak->ak_state != NULL ) { + if ( ak->ak_state->as_desc == ak->ak_desc && + ak->ak_state->as_access == ak->ak_access && + ak->ak_state->as_result != -1 && + ak->ak_state->as_vd_acl == NULL ) { Debug( LDAP_DEBUG_ACL, "=> access_allowed: result was in cache (%s)\n", attr, 0, 0 ); - return state->as_result; + return ak->ak_state->as_result; } else { Debug( LDAP_DEBUG_ACL, "=> access_allowed: result not in cache (%s)\n", @@ -418,9 +388,11 @@ access_allowed_mask( } } + ACL_INIT( ak->ak_mask ); + Debug( LDAP_DEBUG_ACL, "=> access_allowed: %s access to \"%s\" \"%s\" requested\n", - access2str( access ), e->e_dn, attr ); + access2str( ak->ak_access ), ak->ak_e->e_dn, attr ); if ( op == NULL ) { /* no-op call */ @@ -443,22 +415,20 @@ access_allowed_mask( /* this is enforced in backend_add() */ if ( op->o_bd->bd_info->bi_access_allowed ) { /* delegate to backend */ - ret = op->o_bd->bd_info->bi_access_allowed( op, e, - desc, val, access, state, &mask ); + ret = op->o_bd->bd_info->bi_access_allowed( op, ak ); } else { /* use default (but pass through frontend * for global ACL overlays) */ - ret = frontendDB->bd_info->bi_access_allowed( op, e, - desc, val, access, state, &mask ); + ret = frontendDB->bd_info->bi_access_allowed( op, ak ); } if ( !ret ) { - if ( ACL_IS_INVALID( mask ) ) { + if ( ACL_IS_INVALID( ak->ak_mask ) ) { Debug( LDAP_DEBUG_ACL, "=> access_allowed: \"%s\" (%s) invalid!\n", - e->e_dn, attr, 0 ); - ACL_INIT( mask ); + ak->ak_e->e_dn, attr, 0 ); + ACL_INIT( ak->ak_mask ); } else { Debug( LDAP_DEBUG_ACL, @@ -470,17 +440,16 @@ access_allowed_mask( Debug( LDAP_DEBUG_ACL, "=> access_allowed: %s access %s by %s\n", - access2str( access ), ret ? "granted" : "denied", - accessmask2str( mask, accessmaskbuf, 1 ) ); + access2str( ak->ak_access ), ret ? "granted" : "denied", + accessmask2str( ak->ak_mask, accessmaskbuf, 1 ) ); done: - if ( state != NULL ) { - state->as_access = access; - state->as_result = ret; - state->as_desc = desc; + if ( ak->ak_state != NULL ) { + ak->ak_state->as_access = ak->ak_access; + ak->ak_state->as_result = ret; + ak->ak_state->as_desc = ak->ak_desc; } if ( be_null ) op->o_bd = NULL; - if ( maskp ) ACL_PRIV_ASSIGN( *maskp, mask ); return ret; } @@ -493,26 +462,22 @@ done: static AccessControl * slap_acl_get( - AccessControl *a, - int *count, Operation *op, - Entry *e, - AttributeDescription *desc, - struct berval *val, + AclCheck *ak, + AccessControl *a, AclRegexMatches *matches, - slap_mask_t *mask, - AccessControlState *state ) + int *count ) { const char *attr; ber_len_t dnlen; AccessControl *prev; - assert( e != NULL ); + assert( ak->ak_e != NULL ); assert( count != NULL ); - assert( desc != NULL ); - assert( state != NULL ); + assert( ak->ak_desc != NULL ); + assert( ak->ak_state != NULL ); - attr = desc->ad_cname.bv_val; + attr = ak->ak_desc->ad_cname.bv_val; assert( attr != NULL ); @@ -526,27 +491,27 @@ slap_acl_get( assert( a != NULL ); if ( a == frontendDB->be_acl ) - state->as_fe_done = 1; + ak->ak_state->as_fe_done = 1; } else { prev = a; a = a->acl_next; } - dnlen = e->e_nname.bv_len; + dnlen = ak->ak_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 != frontendDB->be_acl && ak->ak_state->as_fe_done ) + ak->ak_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, + ak->ak_e->e_ndn, matches->dn_count, matches->dn_data, 0 ) ) continue; @@ -573,27 +538,27 @@ slap_acl_get( continue; if ( patlen > 0 ) { - if ( !DN_SEPARATOR( e->e_ndn[dnlen - patlen - 1] ) ) + if ( !DN_SEPARATOR( ak->ak_e->e_ndn[dnlen - patlen - 1] ) ) continue; sep = 1; } - rdnlen = dn_rdnlen( NULL, &e->e_nname ); + rdnlen = dn_rdnlen( NULL, &ak->ak_e->e_nname ); if ( rdnlen + patlen + sep != dnlen ) continue; } else if ( a->acl_dn_style == ACL_STYLE_SUBTREE ) { - if ( dnlen > patlen && !DN_SEPARATOR( e->e_ndn[dnlen - patlen - 1] ) ) + if ( dnlen > patlen && !DN_SEPARATOR( ak->ak_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] ) ) + if ( !DN_SEPARATOR( ak->ak_e->e_ndn[dnlen - patlen - 1] ) ) continue; } - if ( strcmp( a->acl_dn_pat.bv_val, e->e_ndn + dnlen - patlen ) != 0 ) + if ( strcmp( a->acl_dn_pat.bv_val, ak->ak_e->e_ndn + dnlen - patlen ) != 0 ) continue; } @@ -601,7 +566,7 @@ slap_acl_get( *count, 0, 0 ); } - if ( a->acl_attrs && !ad_inlist( desc, a->acl_attrs ) ) { + if ( a->acl_attrs && !ad_inlist( ak->ak_desc, a->acl_attrs ) ) { matches->dn_data[0].rm_so = -1; matches->dn_data[0].rm_eo = -1; matches->val_data[0].rm_so = -1; @@ -611,14 +576,14 @@ slap_acl_get( /* Is this ACL only for a specific value? */ if ( a->acl_attrval.bv_len ) { - if ( val == NULL ) { + if ( ak->ak_val == NULL ) { continue; } - 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 ( ak->ak_state->as_vd_acl == NULL ) { + ak->ak_state->as_vd_acl = prev; + ak->ak_state->as_vd_acl_count = *count - 1; + ACL_PRIV_ASSIGN ( ak->ak_state->as_vd_mask, ak->ak_mask ); } if ( a->acl_attrval_style == ACL_STYLE_REGEX ) { @@ -626,7 +591,7 @@ slap_acl_get( "acl_get: valpat %s\n", a->acl_attrval.bv_val, 0, 0 ); if ( regexec ( &a->acl_attrval_re, - val->bv_val, + ak->ak_val->bv_val, matches->val_count, matches->val_data, 0 ) ) { @@ -641,9 +606,9 @@ slap_acl_get( a->acl_attrval.bv_val, 0, 0 ); if ( a->acl_attrs[0].an_desc->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) { - if (value_match( &match, desc, + if (value_match( &match, ak->ak_desc, a->acl_attrval_mr, 0, - val, &a->acl_attrval, &text ) != LDAP_SUCCESS || + ak->ak_val, &a->acl_attrval, &text ) != LDAP_SUCCESS || match ) continue; @@ -651,7 +616,7 @@ slap_acl_get( ber_len_t patlen, vdnlen; patlen = a->acl_attrval.bv_len; - vdnlen = val->bv_len; + vdnlen = ak->ak_val->bv_len; if ( vdnlen < patlen ) continue; @@ -663,33 +628,33 @@ slap_acl_get( } else if ( a->acl_attrval_style == ACL_STYLE_ONE ) { ber_len_t rdnlen = 0; - if ( !DN_SEPARATOR( val->bv_val[vdnlen - patlen - 1] ) ) + if ( !DN_SEPARATOR( ak->ak_val->bv_val[vdnlen - patlen - 1] ) ) continue; - rdnlen = dn_rdnlen( NULL, val ); + rdnlen = dn_rdnlen( NULL, ak->ak_val ); if ( rdnlen + patlen + 1 != vdnlen ) continue; } else if ( a->acl_attrval_style == ACL_STYLE_SUBTREE ) { - if ( vdnlen > patlen && !DN_SEPARATOR( val->bv_val[vdnlen - patlen - 1] ) ) + if ( vdnlen > patlen && !DN_SEPARATOR( ak->ak_val->bv_val[vdnlen - patlen - 1] ) ) continue; } else if ( a->acl_attrval_style == ACL_STYLE_CHILDREN ) { if ( vdnlen <= patlen ) continue; - if ( !DN_SEPARATOR( val->bv_val[vdnlen - patlen - 1] ) ) + if ( !DN_SEPARATOR( ak->ak_val->bv_val[vdnlen - patlen - 1] ) ) continue; } - if ( strcmp( a->acl_attrval.bv_val, val->bv_val + vdnlen - patlen ) ) + if ( strcmp( a->acl_attrval.bv_val, ak->ak_val->bv_val + vdnlen - patlen ) ) continue; } } } if ( a->acl_filter != NULL ) { - ber_int_t rc = test_filter( NULL, e, a->acl_filter ); + ber_int_t rc = test_filter( NULL, ak->ak_e, a->acl_filter ); if ( rc != LDAP_COMPARE_TRUE ) { continue; } @@ -700,8 +665,8 @@ slap_acl_get( return a; } - if ( !state->as_fe_done ) { - state->as_fe_done = 1; + if ( !ak->ak_state->as_fe_done ) { + ak->ak_state->as_fe_done = 1; a = frontendDB->be_acl; goto retry; } @@ -714,18 +679,17 @@ slap_acl_get( * Record value-dependent access control state */ #define ACL_RECORD_VALUE_STATE do { \ - 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 ); \ + if( ak->ak_state && ak->ak_state->as_vd_acl == NULL ) { \ + ak->ak_state->as_vd_acl = a; \ + ak->ak_state->as_vd_acl_count = count; \ + ACL_PRIV_ASSIGN( ak->ak_state->as_vd_mask, ak->ak_mask ); \ } \ } while( 0 ) static int acl_mask_dn( Operation *op, - Entry *e, - struct berval *val, + AclCheck *ak, AccessControl *a, AclRegexMatches *matches, slap_dn_access *bdn, @@ -757,19 +721,19 @@ acl_mask_dn( struct berval ndn, selfndn; int level; - if ( BER_BVISEMPTY( opndn ) || BER_BVISNULL( &e->e_nname ) ) { + if ( BER_BVISEMPTY( opndn ) || BER_BVISNULL( &ak->ak_e->e_nname ) ) { return 1; } level = bdn->a_self_level; if ( level < 0 ) { selfndn = *opndn; - ndn = e->e_nname; + ndn = ak->ak_e->e_nname; level = -level; } else { ndn = *opndn; - selfndn = e->e_nname; + selfndn = ak->ak_e->e_nname; } for ( ; level > 0; level-- ) { @@ -806,7 +770,7 @@ acl_mask_dn( case ACL_STYLE_BASE: tmp_data[0].rm_so = 0; - tmp_data[0].rm_eo = e->e_nname.bv_len; + tmp_data[0].rm_eo = ak->ak_e->e_nname.bv_len; tmp_matches.dn_count = 1; break; @@ -814,9 +778,9 @@ acl_mask_dn( case ACL_STYLE_SUBTREE: case ACL_STYLE_CHILDREN: 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_data[0].rm_eo = ak->ak_e->e_nname.bv_len; + tmp_data[1].rm_so = ak->ak_e->e_nname.bv_len - a->acl_dn_pat.bv_len; + tmp_data[1].rm_eo = ak->ak_e->e_nname.bv_len; tmp_matches.dn_count = 2; break; @@ -831,7 +795,7 @@ acl_mask_dn( } if ( !regex_matches( &bdn->a_pat, opndn->bv_val, - &e->e_nname, NULL, tmp_matchesp ) ) + &ak->ak_e->e_nname, NULL, tmp_matchesp ) ) { return 1; } @@ -842,7 +806,7 @@ acl_mask_dn( ber_len_t patlen, odnlen; int got_match = 0; - if ( e->e_dn == NULL ) + if ( ak->ak_e->e_dn == NULL ) return 1; if ( bdn->a_expand ) { @@ -873,7 +837,7 @@ acl_mask_dn( case ACL_STYLE_BASE: tmp_data[0].rm_so = 0; - tmp_data[0].rm_eo = e->e_nname.bv_len; + tmp_data[0].rm_eo = ak->ak_e->e_nname.bv_len; tmp_matches.dn_count = 1; break; @@ -881,9 +845,9 @@ acl_mask_dn( case ACL_STYLE_SUBTREE: case ACL_STYLE_CHILDREN: 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_data[0].rm_eo = ak->ak_e->e_nname.bv_len; + tmp_data[1].rm_so = ak->ak_e->e_nname.bv_len - a->acl_dn_pat.bv_len; + tmp_data[1].rm_eo = ak->ak_e->e_nname.bv_len; tmp_matches.dn_count = 2; break; @@ -898,8 +862,8 @@ acl_mask_dn( } if ( acl_string_expand( &bv, &bdn->a_pat, - &e->e_nname, - val, tmp_matchesp ) ) + &ak->ak_e->e_nname, + ak->ak_val, tmp_matchesp ) ) { return 1; } @@ -1006,12 +970,9 @@ dn_match_cleanup:; static int acl_mask_dnattr( Operation *op, - Entry *e, - struct berval *val, + AclCheck *ak, AccessControl *a, int count, - AccessControlState *state, - slap_mask_t *mask, slap_dn_access *bdn, struct berval *opndn ) { @@ -1031,7 +992,7 @@ acl_mask_dnattr( bv = *opndn; /* see if asker is listed in dnattr */ - for ( at = attrs_find( e->e_attrs, bdn->a_at ); + for ( at = attrs_find( ak->ak_e->e_attrs, bdn->a_at ); at != NULL; at = attrs_find( at->a_next, bdn->a_at ) ) { @@ -1052,14 +1013,14 @@ acl_mask_dnattr( */ if ( bdn->a_self ) { /* check if the target is an attribute. */ - if ( val == NULL ) return 1; + if ( ak->ak_val == NULL ) return 1; /* target is attribute, check if the attribute value * is the op dn. */ rc = value_match( &match, bdn->a_at, bdn->a_at->ad_type->sat_equality, 0, - val, &bv, &text ); + ak->ak_val, &bv, &text ); /* on match error or no match, fail the ACL clause */ if ( rc != LDAP_SUCCESS || match != 0 ) return 1; @@ -1075,7 +1036,7 @@ acl_mask_dnattr( /* this is a self clause, check if the target is an * attribute. */ - if ( val == NULL ) + if ( ak->ak_val == NULL ) return 1; /* target is attribute, check if the attribute value @@ -1083,7 +1044,7 @@ acl_mask_dnattr( */ rc = value_match( &match, bdn->a_at, bdn->a_at->ad_type->sat_equality, 0, - val, &bv, &text ); + ak->ak_val, &bv, &text ); /* on match error or no match, fail the ACL clause */ if ( rc != LDAP_SUCCESS || match != 0 ) @@ -1105,16 +1066,11 @@ acl_mask_dnattr( static slap_control_t slap_acl_mask( - AccessControl *a, - slap_mask_t *mask, Operation *op, - Entry *e, - AttributeDescription *desc, - struct berval *val, + AclCheck *ak, + AccessControl *a, AclRegexMatches *matches, - int count, - AccessControlState *state, - slap_access_t access ) + int count ) { int i; Access *b; @@ -1127,23 +1083,21 @@ slap_acl_mask( #endif /* SLAP_DYNACL */ assert( a != NULL ); - assert( mask != NULL ); - assert( desc != NULL ); + assert( ak->ak_desc != NULL ); - attr = desc->ad_cname.bv_val; + attr = ak->ak_desc->ad_cname.bv_val; assert( attr != NULL ); Debug( LDAP_DEBUG_ACL, "=> acl_mask: access to entry \"%s\", attr \"%s\" requested\n", - e->e_dn, attr, 0 ); + ak->ak_e->e_dn, attr, 0 ); Debug( LDAP_DEBUG_ACL, "=> acl_mask: to %s by \"%s\", (%s) \n", - val ? "value" : "all values", + ak->ak_val ? "value" : "all values", op->o_ndn.bv_val ? op->o_ndn.bv_val : "", - accessmask2str( *mask, accessmaskbuf, 1 ) ); - + accessmask2str( ak->ak_mask, accessmaskbuf, 1 ) ); b = a->acl_access; i = 1; @@ -1169,7 +1123,7 @@ slap_acl_mask( * is maintained in a_dn_pat. */ - if ( acl_mask_dn( op, e, val, a, matches, + if ( acl_mask_dn( op, ak, a, matches, &b->a_dn, &op->o_ndn ) ) { continue; @@ -1200,7 +1154,7 @@ slap_acl_mask( ndn = op->o_ndn; } - if ( acl_mask_dn( op, e, val, a, matches, + if ( acl_mask_dn( op, ak, a, matches, &b->a_realdn, &ndn ) ) { continue; @@ -1217,7 +1171,7 @@ slap_acl_mask( 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_nname, val, matches ) ) + &ak->ak_e->e_nname, ak->ak_val, matches ) ) { continue; } @@ -1228,7 +1182,7 @@ slap_acl_mask( bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; - if ( acl_string_expand( &bv, &b->a_sockurl_pat, &e->e_nname, val, matches ) ) + if ( acl_string_expand( &bv, &b->a_sockurl_pat, &ak->ak_e->e_nname, ak->ak_val, matches ) ) { continue; } @@ -1256,7 +1210,7 @@ slap_acl_mask( 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_nname, val, matches ) ) + &ak->ak_e->e_nname, ak->ak_val, matches ) ) { continue; } @@ -1272,7 +1226,7 @@ slap_acl_mask( bv.bv_len = sizeof(buf) - 1; bv.bv_val = buf; - if ( acl_string_expand(&bv, &b->a_domain_pat, &e->e_nname, val, matches) ) + if ( acl_string_expand(&bv, &b->a_domain_pat, &ak->ak_e->e_nname, ak->ak_val, matches) ) { continue; } @@ -1310,7 +1264,7 @@ slap_acl_mask( 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_nname, val, matches ) ) + &ak->ak_e->e_nname, ak->ak_val, matches ) ) { continue; } @@ -1328,7 +1282,7 @@ slap_acl_mask( bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; - if ( acl_string_expand( &bv, &b->a_peername_pat, &e->e_nname, val, matches ) ) + if ( acl_string_expand( &bv, &b->a_peername_pat, &ak->ak_e->e_nname, ak->ak_val, matches ) ) { continue; } @@ -1462,7 +1416,7 @@ slap_acl_mask( 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_nname, val, matches ) ) + &ak->ak_e->e_nname, ak->ak_val, matches ) ) { continue; } @@ -1473,7 +1427,7 @@ slap_acl_mask( bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; - if ( acl_string_expand( &bv, &b->a_sockname_pat, &e->e_nname, val, matches ) ) + if ( acl_string_expand( &bv, &b->a_sockname_pat, &ak->ak_e->e_nname, ak->ak_val, matches ) ) { continue; } @@ -1491,8 +1445,8 @@ slap_acl_mask( } if ( b->a_dn_at != NULL ) { - if ( acl_mask_dnattr( op, e, val, a, - count, state, mask, + if ( acl_mask_dnattr( op, ak, a, + count, &b->a_dn, &op->o_ndn ) ) { continue; @@ -1509,8 +1463,8 @@ slap_acl_mask( ndn = op->o_ndn; } - if ( acl_mask_dnattr( op, e, val, a, - count, state, mask, + if ( acl_mask_dnattr( op, ak, a, + count, &b->a_realdn, &ndn ) ) { continue; @@ -1560,7 +1514,7 @@ slap_acl_mask( /* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */ case ACL_STYLE_BASE: tmp_data[0].rm_so = 0; - tmp_data[0].rm_eo = e->e_nname.bv_len; + tmp_data[0].rm_eo = ak->ak_e->e_nname.bv_len; tmp_matches.dn_count = 1; break; @@ -1568,10 +1522,10 @@ slap_acl_mask( case ACL_STYLE_SUBTREE: case ACL_STYLE_CHILDREN: tmp_data[0].rm_so = 0; - tmp_data[0].rm_eo = e->e_nname.bv_len; + tmp_data[0].rm_eo = ak->ak_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_data[1].rm_so = ak->ak_e->e_nname.bv_len - a->acl_dn_pat.bv_len; + tmp_data[1].rm_eo = ak->ak_e->e_nname.bv_len; tmp_matches.dn_count = 2; break; @@ -1586,7 +1540,7 @@ slap_acl_mask( } if ( acl_string_expand( &bv, &b->a_group_pat, - &e->e_nname, val, + &ak->ak_e->e_nname, ak->ak_val, tmp_matchesp ) ) { continue; @@ -1605,7 +1559,7 @@ slap_acl_mask( bv = b->a_group_pat; } - rc = backend_group( op, e, &bv, &op->o_ndn, + rc = backend_group( op, ak->ak_e, &bv, &op->o_ndn, b->a_group_oc, b->a_group_at ); if ( ndn.bv_val ) { @@ -1650,7 +1604,7 @@ slap_acl_mask( /* FALLTHRU: applies also to ACL_STYLE_REGEX when pattern is "*" */ case ACL_STYLE_BASE: tmp_data[0].rm_so = 0; - tmp_data[0].rm_eo = e->e_nname.bv_len; + tmp_data[0].rm_eo = ak->ak_e->e_nname.bv_len; tmp_matches.dn_count = 1; break; @@ -1658,9 +1612,9 @@ slap_acl_mask( case ACL_STYLE_SUBTREE: case ACL_STYLE_CHILDREN: 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; + tmp_data[0].rm_eo = ak->ak_e->e_nname.bv_len; + tmp_data[1].rm_so = ak->ak_e->e_nname.bv_len - a->acl_dn_pat.bv_len; + tmp_data[1].rm_eo = ak->ak_e->e_nname.bv_len; tmp_matches.dn_count = 2; break; default: @@ -1674,7 +1628,7 @@ slap_acl_mask( } if ( acl_string_expand( &bv, &b->a_set_pat, - &e->e_nname, val, + &ak->ak_e->e_nname, ak->ak_val, tmp_matchesp ) ) { continue; @@ -1684,7 +1638,7 @@ slap_acl_mask( bv = b->a_set_pat; } - if ( acl_match_set( &bv, op, e, NULL ) == 0 ) { + if ( acl_match_set( &bv, op, ak->ak_e, NULL ) == 0 ) { continue; } } @@ -1732,11 +1686,11 @@ slap_acl_mask( ACL_RECORD_VALUE_STATE; /* must have DN syntax */ - if ( desc->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName && - !is_at_syntax( desc->ad_type, SLAPD_NAMEUID_SYNTAX )) continue; + if ( ak->ak_desc->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName && + !is_at_syntax( ak->ak_desc->ad_type, SLAPD_NAMEUID_SYNTAX )) continue; /* check if the target is an attribute. */ - if ( val == NULL ) continue; + if ( ak->ak_val == NULL ) continue; /* a DN must be present */ if ( BER_BVISEMPTY( &op->o_ndn ) ) { @@ -1746,9 +1700,9 @@ slap_acl_mask( /* target is attribute, check if the attribute value * is the op dn. */ - rc = value_match( &match, desc, - desc->ad_type->sat_equality, 0, - val, &op->o_ndn, &dummy ); + rc = value_match( &match, ak->ak_desc, + ak->ak_desc->ad_type->sat_equality, 0, + ak->ak_val, &op->o_ndn, &dummy ); /* on match error or no match, fail the ACL clause */ if ( rc != LDAP_SUCCESS || match != 0 ) continue; @@ -1792,8 +1746,8 @@ slap_acl_mask( * 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, + (void)da->da_mask( da->da_private, op, ak->ak_e, ak->ak_desc, + ak->ak_val, matches->dn_count, matches->dn_data, &grant, &deny ); tgrant |= grant; @@ -1842,30 +1796,30 @@ slap_acl_mask( ? "break" : "stop" ); /* save old mask */ - oldmask = *mask; + oldmask = ak->ak_mask; if( ACL_IS_ADDITIVE(modmask) ) { /* add privs */ - ACL_PRIV_SET( *mask, modmask ); + ACL_PRIV_SET( ak->ak_mask, modmask ); /* cleanup */ - ACL_PRIV_CLR( *mask, ~ACL_PRIV_MASK ); + ACL_PRIV_CLR( ak->ak_mask, ~ACL_PRIV_MASK ); } else if( ACL_IS_SUBTRACTIVE(modmask) ) { /* substract privs */ - ACL_PRIV_CLR( *mask, modmask ); + ACL_PRIV_CLR( ak->ak_mask, modmask ); /* cleanup */ - ACL_PRIV_CLR( *mask, ~ACL_PRIV_MASK ); + ACL_PRIV_CLR( ak->ak_mask, ~ACL_PRIV_MASK ); } else { /* assign privs */ - *mask = modmask; + ak->ak_mask = modmask; } Debug( LDAP_DEBUG_ACL, "<= acl_mask: [%d] mask: %s\n", - i, accessmask2str(*mask, accessmaskbuf, 1), 0 ); + i, accessmask2str(ak->ak_mask, accessmaskbuf, 1), 0 ); if( b->a_type == ACL_CONTINUE ) { continue; @@ -1879,11 +1833,11 @@ slap_acl_mask( } /* implicit "by * none" clause */ - ACL_INIT(*mask); + ACL_INIT(ak->ak_mask); Debug( LDAP_DEBUG_ACL, "<= acl_mask: no more clauses, returning %s (stop)\n", - accessmask2str(*mask, accessmaskbuf, 1), 0, 0 ); + accessmask2str(ak->ak_mask, accessmaskbuf, 1), 0, 0 ); return ACL_STOP; } @@ -1900,8 +1854,8 @@ acl_check_modlist( Entry *e, Modifications *mlist ) { - struct berval *bv; AccessControlState state = ACL_STATE_INIT; + AclCheck ak; Backend *be; int be_null = 0; int ret = 1; /* default is access allowed */ @@ -1938,6 +1892,9 @@ acl_check_modlist( goto done; } + ak.ak_e = e; + ak.ak_state = &state; + for ( ; mlist != NULL; mlist = mlist->sml_next ) { /* * Internal mods are ignored by ACL_WRITE checking @@ -1963,6 +1920,7 @@ acl_check_modlist( continue; } + ak.ak_desc = mlist->sml_desc; switch ( mlist->sml_op ) { case LDAP_MOD_REPLACE: case LDAP_MOD_INCREMENT: @@ -1971,10 +1929,9 @@ acl_check_modlist( * attribute and permission to add the specific attributes. * This prevents abuse from selfwriters. */ - if ( ! access_allowed( op, e, - mlist->sml_desc, NULL, - ( mlist->sml_flags & SLAP_MOD_MANAGING ) ? ACL_MANAGE : ACL_WDEL, - &state ) ) + ak.ak_val = NULL; + ak.ak_access = ( mlist->sml_flags & SLAP_MOD_MANAGING ) ? ACL_MANAGE : ACL_WDEL; + if ( ! access_allowed( op, &ak )) { ret = 0; goto done; @@ -1986,15 +1943,13 @@ acl_check_modlist( case LDAP_MOD_ADD: assert( mlist->sml_values != NULL ); + ak.ak_access = ( mlist->sml_flags & SLAP_MOD_MANAGING ) ? ACL_MANAGE : ACL_WADD; - for ( bv = mlist->sml_nvalues + for ( ak.ak_val = mlist->sml_nvalues ? mlist->sml_nvalues : mlist->sml_values; - bv->bv_val != NULL; bv++ ) + ak.ak_val->bv_val != NULL; ak.ak_val++ ) { - if ( ! access_allowed( op, e, - mlist->sml_desc, bv, - ( mlist->sml_flags & SLAP_MOD_MANAGING ) ? ACL_MANAGE : ACL_WADD, - &state ) ) + if ( ! access_allowed( op, &ak )) { ret = 0; goto done; @@ -2004,24 +1959,20 @@ acl_check_modlist( case LDAP_MOD_DELETE: if ( mlist->sml_values == NULL ) { - if ( ! access_allowed( op, e, - mlist->sml_desc, NULL, - ( mlist->sml_flags & SLAP_MOD_MANAGING ) ? ACL_MANAGE : ACL_WDEL, - &state ) ) + ak.ak_val = NULL; + ak.ak_access = ( mlist->sml_flags & SLAP_MOD_MANAGING ) ? ACL_MANAGE : ACL_WDEL; + if ( ! access_allowed( op, &ak )) { ret = 0; goto done; } break; } - for ( bv = mlist->sml_nvalues + for ( ak.ak_val = mlist->sml_nvalues ? mlist->sml_nvalues : mlist->sml_values; - bv->bv_val != NULL; bv++ ) + ak.ak_val->bv_val != NULL; ak.ak_val++ ) { - if ( ! access_allowed( op, e, - mlist->sml_desc, bv, - ( mlist->sml_flags & SLAP_MOD_MANAGING ) ? ACL_MANAGE : ACL_WDEL, - &state ) ) + if ( ! access_allowed( op, &ak )) { ret = 0; goto done; diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 1032008353..4953724f4d 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -1625,11 +1625,11 @@ fe_acl_attribute( BerVarray *vals, slap_access_t access ) { - Entry *e = NULL; void *o_priv = op->o_private, *e_priv = NULL; Attribute *a = NULL; int freeattr = 0, i, j, rc = LDAP_SUCCESS; AccessControlState acl_state = ACL_STATE_INIT; + AclCheck ak; Backend *be = op->o_bd; OpExtra *oex; @@ -1645,30 +1645,34 @@ fe_acl_attribute( op->o_bd = select_backend( edn, 0 ); if ( target && dn_match( &target->e_nname, edn ) ) { - e = target; + ak.ak_e = target; } else { op->o_private = NULL; - rc = be_entry_get_rw( op, edn, NULL, entry_at, 0, &e ); + ak.ak_e = NULL; + rc = be_entry_get_rw( op, edn, NULL, entry_at, 0, &ak.ak_e ); e_priv = op->o_private; op->o_private = o_priv; } - if ( e ) { + if ( ak.ak_e ) { + ak.ak_state = &acl_state; + ak.ak_desc = entry_at; + ak.ak_access = access; if ( entry_at == slap_schema.si_ad_entry || entry_at == slap_schema.si_ad_children ) { assert( vals == NULL ); + ak.ak_val = NULL; rc = LDAP_SUCCESS; if ( op->o_conn && access > ACL_NONE && - access_allowed( op, e, entry_at, NULL, - access, &acl_state ) == 0 ) + access_allowed( op, &ak ) == 0 ) { rc = LDAP_INSUFFICIENT_ACCESS; } goto freeit; } - a = attr_find( e->e_attrs, entry_at ); + a = attr_find( ak.ak_e->e_attrs, entry_at ); if ( a == NULL ) { SlapReply rs = { 0 }; AttributeName anlist[ 2 ]; @@ -1681,7 +1685,7 @@ fe_acl_attribute( /* NOTE: backend_operational() is also called * when returning results, so it's supposed * to do no harm to entries */ - rs.sr_entry = e; + rs.sr_entry = ak.ak_e; rc = backend_operational( op, &rs ); rs.sr_entry = NULL; @@ -1700,8 +1704,7 @@ fe_acl_attribute( BerVarray v; if ( op->o_conn && access > ACL_NONE && - access_allowed( op, e, entry_at, NULL, - access, &acl_state ) == 0 ) + access_allowed( op, &ak ) == 0 ) { rc = LDAP_INSUFFICIENT_ACCESS; goto freeit; @@ -1712,11 +1715,9 @@ fe_acl_attribute( op->o_tmpmemctx ); for ( i = 0, j = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) { + ak.ak_val = &a->a_nvals[i]; if ( op->o_conn && access > ACL_NONE && - access_allowed( op, e, entry_at, - &a->a_nvals[i], - access, - &acl_state ) == 0 ) + access_allowed( op, &ak ) == 0 ) { continue; } @@ -1737,9 +1738,9 @@ fe_acl_attribute( rc = LDAP_SUCCESS; } } -freeit: if ( e != target ) { +freeit: if ( ak.ak_e != target ) { op->o_private = e_priv; - be_entry_release_r( op, e ); + be_entry_release_r( op, ak.ak_e ); op->o_private = o_priv; } if ( freeattr ) { @@ -1781,50 +1782,43 @@ backend_attribute( int backend_access( Operation *op, - Entry *target, - struct berval *edn, - AttributeDescription *entry_at, - struct berval *nval, - slap_access_t access, - slap_mask_t *mask ) + AclCheck *ak, + struct berval *edn ) { - Entry *e = NULL; void *o_priv = op->o_private, *e_priv = NULL; int rc = LDAP_INSUFFICIENT_ACCESS; Backend *be = op->o_bd; + int freeent = 0; /* pedantic */ assert( op != NULL ); assert( op->o_conn != NULL ); assert( edn != NULL ); - assert( access > ACL_NONE ); + assert( ak->ak_access > ACL_NONE ); if ( !op->o_bd ) { op->o_bd = select_backend( edn, 0 ); } - if ( target && dn_match( &target->e_nname, edn ) ) { - e = target; - - } else { + if ( !ak->ak_e || !dn_match( &ak->ak_e->e_nname, edn ) ) { op->o_private = NULL; - rc = be_entry_get_rw( op, edn, NULL, entry_at, 0, &e ); + rc = be_entry_get_rw( op, edn, NULL, ak->ak_desc, 0, &ak->ak_e ); + freeent = 1; e_priv = op->o_private; op->o_private = o_priv; } - if ( e ) { + if ( ak->ak_e ) { Attribute *a = NULL; int freeattr = 0; - if ( entry_at == NULL ) { - entry_at = slap_schema.si_ad_entry; + if ( ak->ak_desc == NULL ) { + ak->ak_desc = slap_schema.si_ad_entry; } - if ( entry_at == slap_schema.si_ad_entry || entry_at == slap_schema.si_ad_children ) + if ( ak->ak_desc == slap_schema.si_ad_entry || ak->ak_desc == slap_schema.si_ad_children ) { - if ( access_allowed_mask( op, e, entry_at, - NULL, access, NULL, mask ) == 0 ) + if ( access_allowed( op, ak ) == 0 ) { rc = LDAP_INSUFFICIENT_ACCESS; @@ -1833,13 +1827,13 @@ backend_access( } } else { - a = attr_find( e->e_attrs, entry_at ); + a = attr_find( ak->ak_e->e_attrs, ak->ak_desc ); if ( a == NULL ) { SlapReply rs = { 0 }; AttributeName anlist[ 2 ]; - anlist[ 0 ].an_name = entry_at->ad_cname; - anlist[ 0 ].an_desc = entry_at; + anlist[ 0 ].an_name = ak->ak_desc->ad_cname; + anlist[ 0 ].an_desc = ak->ak_desc; BER_BVZERO( &anlist[ 1 ].an_name ); rs.sr_attrs = anlist; @@ -1848,7 +1842,7 @@ backend_access( /* NOTE: backend_operational() is also called * when returning results, so it's supposed * to do no harm to entries */ - rs.sr_entry = e; + rs.sr_entry = ak->ak_e; rc = backend_operational( op, &rs ); rs.sr_entry = NULL; @@ -1864,8 +1858,7 @@ backend_access( } if ( a ) { - if ( access_allowed_mask( op, e, entry_at, - nval, access, NULL, mask ) == 0 ) + if ( access_allowed( op, ak ) == 0 ) { rc = LDAP_INSUFFICIENT_ACCESS; goto freeit; @@ -1873,9 +1866,9 @@ backend_access( rc = LDAP_SUCCESS; } } -freeit: if ( e != target ) { +freeit: if ( freeent ) { op->o_private = e_priv; - be_entry_release_r( op, e ); + be_entry_release_r( op, ak->ak_e ); op->o_private = o_priv; } if ( freeattr ) { diff --git a/servers/slapd/backover.c b/servers/slapd/backover.c index ffa0251293..1c4f4e1a23 100644 --- a/servers/slapd/backover.c +++ b/servers/slapd/backover.c @@ -250,12 +250,7 @@ over_back_response ( Operation *op, SlapReply *rs ) static int over_access_allowed( Operation *op, - Entry *e, - AttributeDescription *desc, - struct berval *val, - slap_access_t access, - AccessControlState *state, - slap_mask_t *maskp ) + AclCheck *ak ) { slap_overinfo *oi; slap_overinst *on; @@ -286,8 +281,7 @@ over_access_allowed( } op->o_bd->bd_info = (BackendInfo *)on; - rc = on->on_bi.bi_access_allowed( op, e, - desc, val, access, state, maskp ); + rc = on->on_bi.bi_access_allowed( op, ak ); if ( rc != SLAP_CB_CONTINUE ) break; } } @@ -307,8 +301,7 @@ over_access_allowed( bi_access_allowed = slap_access_allowed; } - rc = bi_access_allowed( op, e, - desc, val, access, state, maskp ); + rc = bi_access_allowed( op, ak ); } /* should not fall thru this far without anything happening... */ if ( rc == SLAP_CB_CONTINUE ) { diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index a04a33ad6d..6a67f3851d 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -4796,13 +4796,18 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs, } if ( op ) { + AclCheck ak; /* No parent, must be root. This will never happen... */ if ( !last && !be_isroot( op ) && !be_shadow_update( op ) ) { return LDAP_NO_SUCH_OBJECT; } - if ( last && !access_allowed( op, last->ce_entry, - slap_schema.si_ad_children, NULL, ACL_WADD, NULL ) ) + ak.ak_e = last->ce_entry; + ak.ak_desc = slap_schema.si_ad_children; + ak.ak_val = NULL; + ak.ak_access = ACL_WADD; + ak.ak_state = NULL; + if ( last && !access_allowed( op, &ak )) { Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: " "DN=\"%s\" no write access to \"children\" of parent\n", @@ -5168,9 +5173,10 @@ config_back_add( Operation *op, SlapReply *rs ) CfBackInfo *cfb; int renumber; ConfigArgs ca; + AclCheck ak = { op->ora_e, slap_schema.si_ad_entry, + NULL, ACL_WADD, NULL }; - if ( !access_allowed( op, op->ora_e, slap_schema.si_ad_entry, - NULL, ACL_WADD, NULL )) { + if ( !access_allowed( op, &ak )) { rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto out; } @@ -5711,6 +5717,7 @@ config_back_modrdn( Operation *op, SlapReply *rs ) CfEntryInfo *ce, *last; struct berval rdn; int ixold, ixnew; + AclCheck ak; cfb = (CfBackInfo *)op->o_bd->be_private; @@ -5721,18 +5728,22 @@ config_back_modrdn( Operation *op, SlapReply *rs ) rs->sr_err = LDAP_NO_SUCH_OBJECT; goto out; } - if ( !access_allowed( op, ce->ce_entry, slap_schema.si_ad_entry, - NULL, ACL_WRITE, NULL )) { + ak.ak_e = ce->ce_entry; + ak.ak_desc = slap_schema.si_ad_entry; + ak.ak_val = NULL; + ak.ak_access = ACL_WRITE; + ak.ak_state = NULL; + if ( !access_allowed( op, &ak )) { rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto out; } - { Entry *parent; + { if ( ce->ce_parent ) - parent = ce->ce_parent->ce_entry; + ak.ak_e = ce->ce_parent->ce_entry; else - parent = (Entry *)&slap_entry_root; - if ( !access_allowed( op, parent, slap_schema.si_ad_children, - NULL, ACL_WRITE, NULL )) { + ak.ak_e = (Entry *)&slap_entry_root; + ak.ak_desc = slap_schema.si_ad_children; + if ( !access_allowed( op, &ak )) { rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto out; } @@ -6014,7 +6025,7 @@ config_back_search( Operation *op, SlapReply *rs ) { CfBackInfo *cfb; CfEntryInfo *ce, *last; - slap_mask_t mask; + AclCheck ak; cfb = (CfBackInfo *)op->o_bd->be_private; @@ -6025,10 +6036,14 @@ config_back_search( Operation *op, SlapReply *rs ) rs->sr_err = LDAP_NO_SUCH_OBJECT; goto out; } - if ( !access_allowed_mask( op, ce->ce_entry, slap_schema.si_ad_entry, NULL, - ACL_SEARCH, NULL, &mask )) + ak.ak_e = ce->ce_entry; + ak.ak_desc = slap_schema.si_ad_entry; + ak.ak_val = NULL; + ak.ak_access = ACL_SEARCH; + ak.ak_state = NULL; + if ( !access_allowed_mask( op, &ak )) { - if ( !ACL_GRANT( mask, ACL_DISCLOSE )) { + if ( !ACL_GRANT( ak.ak_mask, ACL_DISCLOSE )) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { rs->sr_err = LDAP_INSUFFICIENT_ACCESS; diff --git a/servers/slapd/compare.c b/servers/slapd/compare.c index 1e9376a701..4532987066 100644 --- a/servers/slapd/compare.c +++ b/servers/slapd/compare.c @@ -33,8 +33,7 @@ static int compare_entry( Operation *op, - Entry *e, - AttributeAssertion *ava ); + AclCheck *ak ); int do_compare( @@ -144,9 +143,9 @@ cleanup:; int fe_op_compare( Operation *op, SlapReply *rs ) { - Entry *entry = NULL; AttributeAssertion *ava = op->orc_ava; BackendDB *bd = op->o_bd; + AclCheck ak = { NULL }; if( strcasecmp( op->o_req_ndn.bv_val, LDAP_ROOT_DSE ) == 0 ) { if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) { @@ -154,7 +153,7 @@ fe_op_compare( Operation *op, SlapReply *rs ) goto cleanup; } - rs->sr_err = root_dse_info( op->o_conn, &entry, &rs->sr_text ); + rs->sr_err = root_dse_info( op->o_conn, &ak.ak_e, &rs->sr_text ); if( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; @@ -167,7 +166,7 @@ fe_op_compare( Operation *op, SlapReply *rs ) goto cleanup; } - rs->sr_err = schema_info( &entry, &rs->sr_text ); + rs->sr_err = schema_info( &ak.ak_e, &rs->sr_text ); if( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); rs->sr_err = 0; @@ -175,9 +174,13 @@ fe_op_compare( Operation *op, SlapReply *rs ) } } - if( entry ) { - rs->sr_err = compare_entry( op, entry, ava ); - entry_free( entry ); + if( ak.ak_e ) { + ak.ak_desc = ava->aa_desc; + ak.ak_val = &ava->aa_value; + ak.ak_access = ACL_COMPARE; + ak.ak_state = NULL; + rs->sr_err = compare_entry( op, &ak ); + entry_free( ak.ak_e ); send_ldap_result( op, rs ); @@ -240,17 +243,19 @@ fe_op_compare( Operation *op, SlapReply *rs ) { int rc, hasSubordinates = LDAP_SUCCESS; - rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &entry ); - if ( rc == 0 && entry ) { - if ( ! access_allowed( op, entry, - ava->aa_desc, &ava->aa_value, ACL_COMPARE, NULL ) ) + rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &ak.ak_e ); + if ( rc == 0 && ak.ak_e ) { + ak.ak_desc = ava->aa_desc; + ak.ak_val = &ava->aa_value; + ak.ak_access = ACL_COMPARE; + ak.ak_state = NULL; + if ( ! access_allowed( op, &ak )) { rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS; } else { rc = rs->sr_err = op->o_bd->be_has_subordinates( op, - entry, &hasSubordinates ); - be_entry_release_r( op, entry ); + ak.ak_e, &hasSubordinates ); } } @@ -269,13 +274,17 @@ fe_op_compare( Operation *op, SlapReply *rs ) } else { /* return error only if "disclose" * is granted on the object */ - if ( backend_access( op, NULL, &op->o_req_ndn, - slap_schema.si_ad_entry, - NULL, ACL_DISCLOSE, NULL ) == LDAP_INSUFFICIENT_ACCESS ) + ak.ak_desc = slap_schema.si_ad_entry; + ak.ak_val = NULL; + ak.ak_access = ACL_DISCLOSE; + ak.ak_state = NULL; + if ( backend_access( op, &ak, &op->o_req_ndn ) + == LDAP_INSUFFICIENT_ACCESS ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } } + be_entry_release_r( op, ak.ak_e ); send_ldap_result( op, rs ); @@ -307,13 +316,17 @@ fe_op_compare( Operation *op, SlapReply *rs ) rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn, ava->aa_desc, &vals, ACL_COMPARE ); + switch ( rs->sr_err ) { default: /* return error only if "disclose" * is granted on the object */ - if ( backend_access( op, NULL, &op->o_req_ndn, - slap_schema.si_ad_entry, - NULL, ACL_DISCLOSE, NULL ) + ak.ak_e = NULL; + ak.ak_desc = slap_schema.si_ad_entry; + ak.ak_val = NULL; + ak.ak_access = ACL_DISCLOSE; + ak.ak_state = NULL; + if ( backend_access( op, &ak, &op->o_req_ndn ) == LDAP_INSUFFICIENT_ACCESS ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; @@ -354,40 +367,45 @@ cleanup:; static int compare_entry( Operation *op, - Entry *e, - AttributeAssertion *ava ) + AclCheck *ak ) { int rc = LDAP_COMPARE_FALSE; Attribute *a; + AttributeDescription *ad; - if ( ! access_allowed( op, e, - ava->aa_desc, &ava->aa_value, ACL_COMPARE, NULL ) ) + if ( ! access_allowed( op, ak )) { rc = LDAP_INSUFFICIENT_ACCESS; goto done; } - a = attrs_find( e->e_attrs, ava->aa_desc ); + a = attrs_find( ak->ak_e->e_attrs, ak->ak_desc ); if( a == NULL ) { rc = LDAP_NO_SUCH_ATTRIBUTE; goto done; } - for(a = attrs_find( e->e_attrs, ava->aa_desc ); + ad = ak->ak_desc; + for(a = attrs_find( ak->ak_e->e_attrs, ak->ak_desc ); a != NULL; - a = attrs_find( a->a_next, ava->aa_desc )) + a = attrs_find( a->a_next, ak->ak_desc )) { - if (( ava->aa_desc != a->a_desc ) && ! access_allowed( op, - e, a->a_desc, &ava->aa_value, ACL_COMPARE, NULL ) ) - { - rc = LDAP_INSUFFICIENT_ACCESS; - break; + ak->ak_desc = a->a_desc; + if ( a->a_desc != ak->ak_desc ) + { + ak->ak_desc = a->a_desc; + if ( !access_allowed( op, ak )) + { + rc = LDAP_INSUFFICIENT_ACCESS; + break; + } + ak->ak_desc = ad; } if ( attr_valfind( a, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, - &ava->aa_value, NULL, op->o_tmpmemctx ) == 0 ) + ak->ak_val, NULL, op->o_tmpmemctx ) == 0 ) { rc = LDAP_COMPARE_TRUE; break; @@ -396,8 +414,10 @@ static int compare_entry( done: if( rc != LDAP_COMPARE_TRUE && rc != LDAP_COMPARE_FALSE ) { - if ( ! access_allowed( op, e, - slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) + ak->ak_desc = slap_schema.si_ad_entry; + ak->ak_val = NULL; + ak->ak_access = ACL_DISCLOSE; + if ( ! access_allowed( op, ak )) { rc = LDAP_NO_SUCH_OBJECT; } diff --git a/servers/slapd/filterentry.c b/servers/slapd/filterentry.c index 82a36c33d2..1a0b56c93e 100644 --- a/servers/slapd/filterentry.c +++ b/servers/slapd/filterentry.c @@ -163,6 +163,7 @@ static int test_mra_filter( Attribute *a; void *memctx; BER_MEMFREE_FN *memfree; + AclCheck ak; #ifdef LDAP_COMP_MATCH int i, num_attr_vals = 0; #endif @@ -175,14 +176,19 @@ static int test_mra_filter( memfree = op->o_tmpfree; } + ak.ak_e = e; + ak.ak_access = ACL_SEARCH; + ak.ak_state = NULL; + if ( mra->ma_desc ) { /* * if ma_desc is available, then we're filtering for * one attribute, and SEARCH permissions can be checked * directly. */ - if ( !access_allowed( op, e, - mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) ) + ak.ak_desc = mra->ma_desc; + ak.ak_val = &mra->ma_value; + if ( !access_allowed( op, &ak )) { return LDAP_INSUFFICIENT_ACCESS; } @@ -345,8 +351,9 @@ static int test_mra_filter( if ( rc != LDAP_SUCCESS ) continue; /* check search access */ - if ( !access_allowed( op, e, - a->a_desc, &value, ACL_SEARCH, NULL ) ) + ak.ak_desc = a->a_desc; + ak.ak_val = &value; + if ( !access_allowed( op, &ak )) { memfree( value.bv_val, memctx ); continue; @@ -470,8 +477,9 @@ static int test_mra_filter( if ( rc != LDAP_SUCCESS ) continue; /* check search access */ - if ( !access_allowed( op, e, - ad, &value, ACL_SEARCH, NULL ) ) + ak.ak_desc = ad; + ak.ak_val = &value; + if ( !access_allowed( op, &ak )) { memfree( value.bv_val, memctx ); continue; @@ -532,13 +540,13 @@ test_ava_filter( { int rc; Attribute *a; + AclCheck ak = { e, ava->aa_desc, &ava->aa_value, ACL_SEARCH, NULL }; #ifdef LDAP_COMP_MATCH int i, num_attr_vals = 0; AttributeAliasing *a_alias = NULL; #endif - if ( !access_allowed( op, e, - ava->aa_desc, &ava->aa_value, ACL_SEARCH, NULL ) ) + if ( !access_allowed( op, &ak )) { return LDAP_INSUFFICIENT_ACCESS; } @@ -620,11 +628,17 @@ test_ava_filter( MatchingRule *mr; struct berval *bv; - if (( ava->aa_desc != a->a_desc ) && !access_allowed( op, - e, a->a_desc, &ava->aa_value, ACL_SEARCH, NULL )) + if ( ava->aa_desc != a->a_desc ) { - rc = LDAP_INSUFFICIENT_ACCESS; - continue; + int ret; + ak.ak_desc = a->a_desc; + ret = access_allowed( op, &ak ); + ak.ak_desc = ava->aa_desc; + if ( !ret ) + { + rc = LDAP_INSUFFICIENT_ACCESS; + continue; + } } use = SLAP_MR_EQUALITY; @@ -817,8 +831,9 @@ test_presence_filter( { Attribute *a; int rc; + AclCheck ak = { e, desc, NULL, ACL_SEARCH, NULL }; - if ( !access_allowed( op, e, desc, NULL, ACL_SEARCH, NULL ) ) { + if ( !access_allowed( op, &ak ) ) { return LDAP_INSUFFICIENT_ACCESS; } @@ -849,11 +864,17 @@ test_presence_filter( a != NULL; a = attrs_find( a->a_next, desc ) ) { - if (( desc != a->a_desc ) && !access_allowed( op, - e, a->a_desc, NULL, ACL_SEARCH, NULL )) + if ( desc != a->a_desc ) { - rc = LDAP_INSUFFICIENT_ACCESS; - continue; + int ret; + ak.ak_desc = a->a_desc; + ret = access_allowed( op, &ak ); + ak.ak_desc = desc; + if ( !ret ) + { + rc = LDAP_INSUFFICIENT_ACCESS; + continue; + } } rc = LDAP_COMPARE_TRUE; @@ -934,11 +955,11 @@ test_substrings_filter( { Attribute *a; int rc; + AclCheck ak = { e, f->f_sub_desc, NULL, ACL_SEARCH, NULL }; Debug( LDAP_DEBUG_FILTER, "begin test_substrings_filter\n", 0, 0, 0 ); - if ( !access_allowed( op, e, - f->f_sub_desc, NULL, ACL_SEARCH, NULL ) ) + if ( !access_allowed( op, &ak )) { return LDAP_INSUFFICIENT_ACCESS; } @@ -952,11 +973,17 @@ test_substrings_filter( MatchingRule *mr; struct berval *bv; - if (( f->f_sub_desc != a->a_desc ) && !access_allowed( op, - e, a->a_desc, NULL, ACL_SEARCH, NULL )) + if ( f->f_sub_desc != a->a_desc ) { - rc = LDAP_INSUFFICIENT_ACCESS; - continue; + int ret; + ak.ak_desc = a->a_desc; + ret = access_allowed( op, &ak ); + ak.ak_desc = f->f_sub_desc; + if ( !ret ) + { + rc = LDAP_INSUFFICIENT_ACCESS; + continue; + } } mr = a->a_desc->ad_type->sat_substr; diff --git a/servers/slapd/passwd.c b/servers/slapd/passwd.c index 15908cec84..9dc82145b0 100644 --- a/servers/slapd/passwd.c +++ b/servers/slapd/passwd.c @@ -505,9 +505,9 @@ slap_passwd_check( const char **text ) { int result = 1; - struct berval *bv; AccessControlState acl_state = ACL_STATE_INIT; char credNul = cred->bv_val[cred->bv_len]; + AclCheck ak; #ifdef SLAPD_SPASSWD void *old_authctx = NULL; @@ -518,15 +518,19 @@ slap_passwd_check( if ( credNul ) cred->bv_val[cred->bv_len] = 0; - for ( bv = a->a_vals; bv->bv_val != NULL; bv++ ) { + ak.ak_e = e; + ak.ak_desc = a->a_desc; + ak.ak_access = ACL_AUTH; + ak.ak_state = &acl_state; + + for ( ak.ak_val = a->a_vals; ak.ak_val->bv_val != NULL; ak.ak_val++ ) { /* if e is provided, check access */ - if ( e && access_allowed( op, e, a->a_desc, bv, - ACL_AUTH, &acl_state ) == 0 ) + if ( e && access_allowed( op, &ak ) == 0 ) { continue; } - if ( !lutil_passwd( bv, cred, NULL, text ) ) { + if ( !lutil_passwd( ak.ak_val, cred, NULL, text ) ) { result = 0; break; } diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 62ea62815e..58e04e43e9 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -46,29 +46,15 @@ LDAP_SLAPD_F (int) dynacl_aci_init LDAP_P(( void )); /* * acl.c */ -LDAP_SLAPD_F (int) access_allowed_mask LDAP_P(( - Operation *op, - Entry *e, AttributeDescription *desc, struct berval *val, - slap_access_t access, - AccessControlState *state, - slap_mask_t *mask )); +LDAP_SLAPD_F (int) access_allowed LDAP_P(( + Operation *op, AclCheck *ak )); +#if 0 #define access_allowed(op,e,desc,val,access,state) access_allowed_mask(op,e,desc,val,access,state,NULL) +#endif LDAP_SLAPD_F (int) slap_access_allowed LDAP_P(( - Operation *op, - Entry *e, - AttributeDescription *desc, - struct berval *val, - slap_access_t access, - AccessControlState *state, - slap_mask_t *maskp )); + Operation *op, AclCheck *ak )); LDAP_SLAPD_F (int) slap_access_always_allowed LDAP_P(( - Operation *op, - Entry *e, - AttributeDescription *desc, - struct berval *val, - slap_access_t access, - AccessControlState *state, - slap_mask_t *maskp )); + Operation *op, AclCheck *ak )); LDAP_SLAPD_F (int) acl_check_modlist LDAP_P(( Operation *op, Entry *e, Modifications *ml )); @@ -416,12 +402,8 @@ LDAP_SLAPD_F (int) backend_attribute LDAP_P(( LDAP_SLAPD_F (int) backend_access LDAP_P(( Operation *op, - Entry *target, - struct berval *edn, - AttributeDescription *entry_at, - struct berval *nval, - slap_access_t access, - slap_mask_t *mask )); + AclCheck *ak, + struct berval *edn )); LDAP_SLAPD_F (int) backend_operational LDAP_P(( Operation *op, @@ -2043,12 +2025,7 @@ LDAP_SLAPD_F (int) fe_acl_attribute LDAP_P(( slap_access_t access )); LDAP_SLAPD_F (int) fe_access_allowed LDAP_P(( Operation *op, - Entry *e, - AttributeDescription *desc, - struct berval *val, - slap_access_t access, - AccessControlState *state, - slap_mask_t *maskp )); + AclCheck *ak )); /* NOTE: this macro assumes that bv has been allocated * by ber_* malloc functions or is { 0L, NULL } */ diff --git a/servers/slapd/result.c b/servers/slapd/result.c index e89090db14..2014864e85 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -847,6 +847,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) AccessControlState acl_state = ACL_STATE_INIT; int attrsonly; AttributeDescription *ad_entry = slap_schema.si_ad_entry; + AclCheck ak; /* a_flags: array of flags telling if the i-th element will be * returned or filtered out @@ -896,7 +897,12 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) attrsonly = op->ors_attrsonly; - if ( !access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL )) { + ak.ak_e = rs->sr_entry; + ak.ak_desc = ad_entry; + ak.ak_val = NULL; + ak.ak_access = ACL_READ; + ak.ak_state = NULL; + if ( !access_allowed( op, &ak )) { Debug( LDAP_DEBUG_ACL, "send_search_entry: conn %lu access to entry (%s) not allowed\n", op->o_connid, rs->sr_entry->e_name.bv_val, 0 ); @@ -999,6 +1005,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) } } + ak.ak_state = &acl_state; for ( a = rs->sr_entry->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) { AttributeDescription *desc = a->a_desc; int finish = 0; @@ -1029,9 +1036,9 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) } } + ak.ak_desc = desc; if ( attrsonly ) { - if ( ! access_allowed( op, rs->sr_entry, desc, NULL, - ACL_READ, &acl_state ) ) + if ( ! access_allowed( op, &ak )) { Debug( LDAP_DEBUG_ACL, "send_search_entry: " "conn %lu access to attribute %s not allowed\n", @@ -1055,8 +1062,8 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) } else { int first = 1; for ( i = 0; a->a_nvals[i].bv_val != NULL; i++ ) { - if ( ! access_allowed( op, rs->sr_entry, - desc, &a->a_nvals[i], ACL_READ, &acl_state ) ) + ak.ak_val = &a->a_nvals[i]; + if ( ! access_allowed( op, &ak )) { Debug( LDAP_DEBUG_ACL, "send_search_entry: conn %lu " @@ -1190,8 +1197,8 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) } } - if ( ! access_allowed( op, rs->sr_entry, desc, NULL, - ACL_READ, &acl_state ) ) + ak.ak_desc = desc; + if ( ! access_allowed( op, &ak )) { Debug( LDAP_DEBUG_ACL, "send_search_entry: conn %lu " @@ -1216,8 +1223,8 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) if ( ! attrsonly ) { for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) { - if ( ! access_allowed( op, rs->sr_entry, - desc, &a->a_vals[i], ACL_READ, &acl_state ) ) + ak.ak_val = &a->a_vals[i]; + if ( ! access_allowed( op, &ak )) { Debug( LDAP_DEBUG_ACL, "send_search_entry: conn %lu " @@ -1383,25 +1390,29 @@ slap_send_search_reference( Operation *op, SlapReply *rs ) "=> send_search_reference: dn=\"%s\"\n", edn, 0, 0 ); - if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry, - ad_entry, NULL, ACL_READ, NULL ) ) + if ( rs->sr_entry ) { - Debug( LDAP_DEBUG_ACL, - "send_search_reference: access to entry not allowed\n", - 0, 0, 0 ); - rc = 1; - goto rel; - } + AclCheck ak = { rs->sr_entry, ad_entry, NULL, ACL_READ, NULL }; - if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry, - ad_ref, NULL, ACL_READ, NULL ) ) - { - Debug( LDAP_DEBUG_ACL, - "send_search_reference: access " - "to reference not allowed\n", - 0, 0, 0 ); - rc = 1; - goto rel; + if ( !access_allowed( op, &ak )) + { + Debug( LDAP_DEBUG_ACL, + "send_search_reference: access to entry not allowed\n", + 0, 0, 0 ); + rc = 1; + goto rel; + } + + ak.ak_desc = ad_ref; + if ( !access_allowed( op, &ak )) + { + Debug( LDAP_DEBUG_ACL, + "send_search_reference: access " + "to reference not allowed\n", + 0, 0, 0 ); + rc = 1; + goto rel; + } } if( op->o_domain_scope ) { diff --git a/servers/slapd/sasl.c b/servers/slapd/sasl.c index 279731f40b..820f2936b4 100644 --- a/servers/slapd/sasl.c +++ b/servers/slapd/sasl.c @@ -178,9 +178,15 @@ sasl_ap_lookup( Operation *op, SlapReply *rs ) const char *text; int rc, i; lookup_info *sl = (lookup_info *)op->o_callback->sc_private; + AclCheck ak; if (rs->sr_type != REP_SEARCH) return 0; + ak.ak_e = rs->sr_entry; + ak.ak_val = NULL; + ak.ak_access = ACL_AUTH; + ak.ak_state = NULL; + for( i = 0; sl->list[i].name; i++ ) { const char *name = sl->list[i].name; @@ -215,7 +221,8 @@ sasl_ap_lookup( Operation *op, SlapReply *rs ) a = attr_find( rs->sr_entry->e_attrs, ad ); if ( !a ) continue; - if ( ! access_allowed( op, rs->sr_entry, ad, NULL, ACL_AUTH, NULL ) ) { + ak.ak_desc = ad; + if ( ! access_allowed( op, &ak ) ) { continue; } if ( sl->list[i].values && ( sl->flags & SASL_AUXPROP_OVERRIDE ) ) { diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 567f356654..2babb3b5c6 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1298,38 +1298,6 @@ typedef struct AuthorizationInformation { slap_ssf_t sai_sasl_ssf; /* SASL SSF */ } AuthorizationInformation; -#ifdef SLAP_DYNACL - -/* - * "dynamic" ACL infrastructure (for ACIs and more) - */ -typedef int (slap_dynacl_parse) LDAP_P(( const char *fname, int lineno, - const char *opts, slap_style_t, const char *, void **privp )); -typedef int (slap_dynacl_unparse) LDAP_P(( void *priv, struct berval *bv )); -typedef int (slap_dynacl_mask) LDAP_P(( - void *priv, - Operation *op, - Entry *e, - AttributeDescription *desc, - struct berval *val, - int nmatch, - regmatch_t *matches, - slap_access_t *grant, - slap_access_t *deny )); -typedef int (slap_dynacl_destroy) LDAP_P(( void *priv )); - -typedef struct slap_dynacl_t { - char *da_name; - slap_dynacl_parse *da_parse; - slap_dynacl_unparse *da_unparse; - slap_dynacl_mask *da_mask; - slap_dynacl_destroy *da_destroy; - - void *da_private; - struct slap_dynacl_t *da_next; -} slap_dynacl_t; -#endif /* SLAP_DYNACL */ - /* the DN portion of the "by" part */ typedef struct slap_dn_access { /* DN pattern */ @@ -1549,6 +1517,15 @@ typedef struct AccessControlState { } AccessControlState; #define ACL_STATE_INIT { NULL, ACL_NONE, NULL, 0, ACL_PRIV_NONE, -1, 0 } +typedef struct AclCheck { + Entry *ak_e; + AttributeDescription *ak_desc; + struct berval *ak_val; + slap_access_t ak_access; + AccessControlState *ak_state; + slap_mask_t ak_mask; +} AclCheck; + typedef struct AclRegexMatches { int dn_count; regmatch_t dn_data[MAXREMATCHES]; @@ -1556,6 +1533,38 @@ typedef struct AclRegexMatches { regmatch_t val_data[MAXREMATCHES]; } AclRegexMatches; +#ifdef SLAP_DYNACL + +/* + * "dynamic" ACL infrastructure (for ACIs and more) + */ +typedef int (slap_dynacl_parse) LDAP_P(( const char *fname, int lineno, + const char *opts, slap_style_t, const char *, void **privp )); +typedef int (slap_dynacl_unparse) LDAP_P(( void *priv, struct berval *bv )); +typedef int (slap_dynacl_mask) LDAP_P(( + void *priv, + Operation *op, + Entry *e, + AttributeDescription *desc, + struct berval *val, + int nmatch, + regmatch_t *matches, + slap_access_t *grant, + slap_access_t *deny )); +typedef int (slap_dynacl_destroy) LDAP_P(( void *priv )); + +typedef struct slap_dynacl_t { + char *da_name; + slap_dynacl_parse *da_parse; + slap_dynacl_unparse *da_unparse; + slap_dynacl_mask *da_mask; + slap_dynacl_destroy *da_destroy; + + void *da_private; + struct slap_dynacl_t *da_next; +} slap_dynacl_t; +#endif /* SLAP_DYNACL */ + /* * Backend-info * represents a backend @@ -2145,9 +2154,7 @@ typedef int (BI_entry_get_rw) LDAP_P(( Operation *op, struct berval *ndn, typedef int (BI_operational) LDAP_P(( Operation *op, SlapReply *rs )); typedef int (BI_has_subordinates) LDAP_P(( Operation *op, Entry *e, int *hasSubs )); -typedef int (BI_access_allowed) LDAP_P(( Operation *op, Entry *e, - AttributeDescription *desc, struct berval *val, slap_access_t access, - AccessControlState *state, slap_mask_t *maskp )); +typedef int (BI_access_allowed) LDAP_P(( Operation *op, AclCheck *ak )); typedef int (BI_acl_group) LDAP_P(( Operation *op, Entry *target, struct berval *gr_ndn, struct berval *op_ndn, ObjectClass *group_oc, AttributeDescription *group_at )); diff --git a/servers/slapd/slapacl.c b/servers/slapd/slapacl.c index c02d5db3b1..7041bb28cb 100644 --- a/servers/slapd/slapacl.c +++ b/servers/slapd/slapacl.c @@ -38,24 +38,21 @@ static int print_access( Operation *op, - Entry *e, - AttributeDescription *desc, - struct berval *val, - struct berval *nval ) + AclCheck *ak, + struct berval *val ) { int rc; - slap_mask_t mask; char accessmaskbuf[ACCESSMASK_MAXLEN]; - rc = access_allowed_mask( op, e, desc, nval, ACL_AUTH, NULL, &mask ); + rc = access_allowed( op, ak ); fprintf( stderr, "%s%s%s: %s\n", - desc->ad_cname.bv_val, - ( val && !BER_BVISNULL( val ) ) ? "=" : "", - ( val && !BER_BVISNULL( val ) ) ? - ( desc == slap_schema.si_ad_userPassword ? - "****" : val->bv_val ) : "", - accessmask2str( mask, accessmaskbuf, 1 ) ); + ak->ak_desc->ad_cname.bv_val, + ( ak->ak_val && !BER_BVISNULL( ak->ak_val ) ) ? "=" : "", + ( ak->ak_val && !BER_BVISNULL( ak->ak_val ) ) ? + ( ak->ak_desc == slap_schema.si_ad_userPassword ? + "****" : ak->ak_val->bv_val ) : "", + accessmask2str( ak->ak_mask, accessmaskbuf, 1 ) ); return rc; } @@ -74,6 +71,7 @@ slapacl( int argc, char **argv ) int doclose = 0; BackendDB *bd; void *thrctx; + AclCheck ak; slap_tool_init( progname, SLAPACL, argc, argv ); @@ -277,33 +275,36 @@ slapacl( int argc, char **argv ) } + ak.ak_e = ep; + ak.ak_access = ACL_AUTH; + ak.ak_state = NULL; + if ( argc == 0 ) { Attribute *a; - (void)print_access( op, ep, slap_schema.si_ad_entry, NULL, NULL ); - (void)print_access( op, ep, slap_schema.si_ad_children, NULL, NULL ); + ak.ak_val = NULL; + ak.ak_desc = slap_schema.si_ad_entry; + (void)print_access( op, &ak, NULL ); + ak.ak_desc = slap_schema.si_ad_children; + (void)print_access( op, &ak, NULL ); for ( a = ep->e_attrs; a; a = a->a_next ) { int i; for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) { - (void)print_access( op, ep, a->a_desc, - &a->a_vals[ i ], - &a->a_nvals[ i ] ); + ak.ak_desc = a->a_desc; + ak.ak_val = &a->a_nvals[i]; + (void)print_access( op, &ak, &a->a_vals[ i ] ); } } } } for ( ; argc--; argv++ ) { - slap_mask_t mask; - AttributeDescription *desc = NULL; - struct berval val = BER_BVNULL, - *valp = NULL; + struct berval val = BER_BVNULL; const char *text; char accessmaskbuf[ACCESSMASK_MAXLEN]; char *accessstr; - slap_access_t access = ACL_AUTH; if ( attr == NULL ) { attr = argv[ 0 ]; @@ -314,17 +315,20 @@ slapacl( int argc, char **argv ) val.bv_val[0] = '\0'; val.bv_val++; val.bv_len = strlen( val.bv_val ); - valp = &val; + ak.ak_val = &val; + } else { + ak.ak_val = NULL; } + ak.ak_access = ACL_AUTH; accessstr = strchr( attr, '/' ); if ( accessstr != NULL ) { int invalid = 0; accessstr[0] = '\0'; accessstr++; - access = str2access( accessstr ); - switch ( access ) { + ak.ak_access = str2access( accessstr ); + switch ( ak.ak_access ) { case ACL_INVALID_ACCESS: fprintf( stderr, "unknown access \"%s\" for attribute \"%s\"\n", accessstr, attr ); @@ -349,7 +353,8 @@ slapacl( int argc, char **argv ) } } - rc = slap_str2ad( attr, &desc, &text ); + ak.ak_desc = NULL; + rc = slap_str2ad( attr, &ak.ak_desc, &text ); if ( rc != LDAP_SUCCESS ) { fprintf( stderr, "slap_str2ad(%s) failed %d (%s)\n", attr, rc, ldap_err2string( rc ) ); @@ -359,23 +364,22 @@ slapacl( int argc, char **argv ) break; } - rc = access_allowed_mask( op, ep, desc, valp, access, - NULL, &mask ); + rc = access_allowed( op, &ak ); if ( accessstr ) { fprintf( stderr, "%s access to %s%s%s: %s\n", accessstr, - desc->ad_cname.bv_val, + ak.ak_desc->ad_cname.bv_val, val.bv_val ? "=" : "", val.bv_val ? val.bv_val : "", rc ? "ALLOWED" : "DENIED" ); } else { fprintf( stderr, "%s%s%s: %s\n", - desc->ad_cname.bv_val, + ak.ak_desc->ad_cname.bv_val, val.bv_val ? "=" : "", val.bv_val ? val.bv_val : "", - accessmask2str( mask, accessmaskbuf, 1 ) ); + accessmask2str( ak.ak_mask, accessmaskbuf, 1 ) ); } rc = 0; attr = NULL; -- 2.47.2